Здесь странное поведение, в которое я попал, и я не могу найти никакого намека на то, почему это так. Я использую в этом примере метод оценки SizeEstimator от Spark, но я не обнаружил никаких сбоев в их коде, поэтому мне интересно, почему - если они предоставляют хорошая оценка памяти - почему у меня это есть:
val buf1 = new ArrayBuffer[(Int,Double)]
var i = 0
while (i < 3) {
buf1 += ((i,i.toDouble))
i += 1
}
System.out.println(s"Raw size with doubles: ${SizeEstimator.estimate(buf1)}")
val ite1 = buf1.toIterator
var size1: Long = 0l
while (ite1.hasNext) {
val cur = ite1.next()
size1 += SizeEstimator.estimate(cur)
}
System.out.println(s"Size with doubles: $size1")
val buf2 = new ArrayBuffer[(Int,Float)]
i = 0
while (i < 3) {
buf2 += ((i,i.toFloat))
i += 1
}
System.out.println(s"Raw size with floats: ${SizeEstimator.estimate(buf2)}")
val ite2 = buf2.toIterator
var size2: Long = 0l
while (ite2.hasNext) {
val cur = ite2.next()
size2 += SizeEstimator.estimate(cur)
}
System.out.println(s"Size with floats: $size2")
Выход на консоль печатает:
Raw size with doubles: 200
Size with doubles: 96
Raw size with floats: 272
Size with floats: 168
Итак, мой вопрос довольно наивный: почему в этом случае float имеет больше памяти, чем удваивается? И почему это становится еще хуже, когда я превращаю его в итератор (в первом случае соотношение 75% составляет 50% при преобразовании в итератор!).
(Чтобы иметь больше контекста, я впал в это, пытаясь "оптимизировать" приложение Spark, изменив Double
на Float
и выяснив, что на самом деле это заняло больше памяти с поплавками, чем с удвоением...)
P.S.: это не из-за малого размера буферов (здесь 3), если я ставлю 100, я получаю:
Raw size with doubles: 3752
Size with doubles: 3200
Raw size with floats: 6152
Size with floats: 5600
и поплавки все еще потребляют больше памяти... Но соотношение стабилизировалось, поэтому кажется, что разные отношения при преобразовании в итератор должны быть обусловлены некоторыми накладными расходами, которые, как я полагаю.
EDIT: Похоже, что Product2
фактически специализируется только на Int
, Long
и Double
:
trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Double) +T2] extends Any with Product
Кто-нибудь знает, почему Float
не учитывается? Ни Short
, что приводит к странным поведением...