如何估计scala中数据结构的大小?

时间:2012-06-26 14:03:24

标签: performance scala jvm

我的查询返回了大约600万行,这个行太大了,无法在内存中同时处理所有行。

每个查询都返回一个Tuple3 [String,Int,java.sql.Timestamp]。我知道字符串绝不会超过20个字符,UTF8。

如何计算其中一个元组的最大大小,更一般地说,我如何估计这样的scala数据结构的大小?

我正在使用的机器上有6Gb。但是,正在使用scala-query从数据库中读取数据到scala的列表中。

2 个答案:

答案 0 :(得分:6)

Scala对象遵循与Java对象大致相同的规则,因此有关这些对象的任何信息都是准确的。 Here is one source,这似乎至少适用于32位JVM。 (64位JVM每个指针使用8个字节,这通常可以达到4个字节的额外开销加上每个指针4个字节 - 但是如果JVM使用压缩指针可能会少一些,我认为现在默认情况下会这样做。)

我假设没有压缩指针的64位机器(最坏的情况);那么Tuple3有两个指针(16个字节)加上一个Int(4个字节)加上对象开销(~12个字节)四舍五入到最接近的8个或32个字节,加上一个额外的对象(8个字节) )作为非专业版Int的存根。 (遗憾的是,如果在元组中使用原语,它们甚至比使用包装版本时更多更多空间。) String是32字节,IIRC,加上数据的数组,每个字符16加2。 java.sql.Timestamp需要存储几个Long(我认为是),所以这是32个字节。总而言之,它的大小为120字节加上每个字符两个,大约20个字符是~160字节。

或者,请参阅this answer以了解直接测量对象大小的方法。当我以这种方式测量它时,我得到160个字节(并且上面的估计已经使用这些数据进行了校正,因此它匹配;之前我有几个小错误。)

答案 1 :(得分:2)

你有多少记忆力可供你使用? 600万的三联实例真的不是很多!

每个引用的开销为4或8个字节,具体取决于您是运行32位还是64位(没有压缩的“oops”,尽管这是JDK7中32Gb以下的默认值)。

所以你的三元组有3个引用(由于专业化可能有额外的引用 - 所以你可能得到4个引用),你的Timestamplong周围的包装器(引用)(8个字节) 。您的Int将是专用的(即基础int),因此这将产生另外4个字节。字符串是20 x 2字节。所以你基本上有一个 每行100字节的最坏情况;所以每kb 10行,每Mb 10,000行。因此,您可以在1 Gb的堆中轻松处理600万行。

坦率地说,我认为我在这里犯了一个错误,因为我们在这个空间里每天处理几百万行大约二十个字段(包括小数,字符串等)。