方法是否用类实例化,消耗大量内存(在Scala中)?

时间:2016-09-22 08:59:23

标签: python scala oop jvm

情况

我将构建一个程序(在Scala或Python中 - 尚未决定),这是一个强大的数据操作。我看到两个市长的方法:

  1. 方法:定义数据集合。写我的功能。通过函数发送整个数据集。
  2. 方法:定义表示单个数据实体的数据类,并将方法(类成员)编码到数据类中。应该灵活的方法部分通过Scala Function或Python lambda发送给方法。
  3. 附带问题

    我不确定,但第一种方法可能是更多的功能性编程,第二种方法是OOP,是吗?顺便说一句,我喜欢功能编程和OOP(有人说他们彼此相反,但是Odersky尽力反驳Scala)。

    主要问题

    我更喜欢第二种方法,因为

    1. 对我来说似乎更简洁。
    2. 它使得在无共享架构大数据设置中分发程序变得更加容易,因为它根据数据局部性原则为数据而不是数据提供功能。
    3. 然而,我担心如果我有很多数据(而且我这样做),我将消耗大量内存,因为该方法可能需要多次实例化。

      1. 问题: Scala / JVM是否属实 - 如果不是,它是如何解决的?
      2. 问题:对Python来说是否属实?如果没有,它是如何解决的?
      3. 后续问题

        引导我:我应该选择哪种方法?

        更多上下文

        • 我有很多数据(数百万,可能是数十亿的数据对象)
        • 我没有那么多功能可以实现。为了给出一个大概的数字,让我们说一下10。
        • 我期待很多方法调用。
        • 假设我每个数据实体有100个电话,那么我将有100 * 100万个电话用于整个节目。
        • 我的数据类代表单个实体,而不是整个数据集。
        • 我担心的是,在我的DataObject类的每个实例化中,需要复制方法的代码,这会花费大量的内存和处理能力。我不知道JVM和Python的内部如何在这方面工作以及这是否正确 - 这就是我的要求。

        这是一个粗糙的DataObject类:

        class DataObject {
        
            List datavalues
        
            def mymethod(){
                ...
            }
        }
        

1 个答案:

答案 0 :(得分:1)

哪种方法最好完全取决于您的问题。如果只有很少的操作,功能就更简单了。如果您有许多操作依赖于数据的类型/特征,则类是有效的。

就个人而言,我更喜欢使用相同类型数据的类来改进抽象和模块化。基本上,使用类需要您考虑数据是什么样的,允许的数据以及适当的数据。它强制您分离,划分和了解您正在做的事情。完成后,您可以将它们视为可以正常工作的黑盒子。

我看到很多数据分析程序都失败了,因为它们只有处理任意数据的函数。起初,这是简单的计算。然后需要保存/缓存状态,因此直接附加或修改数据。然后有人意识到,如果你在之前不做之前做了x,那么各种各样的旗帜,领域和其他东西都会被加上,只有a,b和d才能被理解。然后有人添加了功能f,扩展了它,而有人添加了功能k,扩展它的方式不同。这会创建一个在创建结果时无法理解,维护或信任的集群foo。

所以如果你不确定,那就上课吧。最后你会更开心。

关于你的第二个问题,我只能回答python的问题。但是,许多语言也是这样做的。

python中的常规方法在类上定义并使用它创建。这意味着方法表示的实际函数由所有实例共享,没有内存开销。基本上,裸实例只是对类的包装引用,从中提取方法。只有独占的实例(如数据)才能显着增加内存。

调用方法会增加一些开销,因为该方法被绑定到实例 - 基本上,该函数是从类中获取的,并且第一个参数self被绑定。这在技术上会产生一些开销。

# Method Call
$ python -m timeit -s 'class Foo():' -s ' def p(self):' -s '  pass' -s 'foo = Foo()' 'foo.p()'
10000000 loops, best of 3: 0.158 usec per loop
# Method Call of cached method
$ python -m timeit -s 'class Foo():' -s ' def p(self):' -s '  pass' -s 'foo = Foo()' -s 'p=foo.p' 'p()'
10000000 loops, best of 3: 0.0984 usec per loop
# Function Call
$ python -m timeit -s 'def p():' -s ' pass' 'p()'
10000000 loops, best of 3: 0.0846 usec per loop

然而,实际上任何操作都是这样做的;如果您的应用程序除了调用您的方法之外什么都不做,那么您只会注意到增加的开销,并且该方法也没有做任何事情。

我也看到人们编写具有如此多抽象级别的数据分析应用程序,实际上他们大多只是调用方法/函数。这是一般编写代码的气味,而不是使用方法函数。

所以如果你不确定,那就上课吧。最后你会更开心。