reales - Scala: ¿por qué Double consume menos memoria que Floats en este caso?
libro de android studio en español pdf (1)
Esto se debe a que Tuple2
está @specialized
para Double
pero no está especializado en Float
.
Eso significa que (Int,Double)
se presentará como una estructura con 2 campos de tipos java primitivos int
y double
, mientras que (Int,Float)
se presentará como una estructura con campos int
y wrapper tipo java.lang.Float
Más discusión aquí
Aquí hay un comportamiento extraño en el que caí y no puedo encontrar ninguna pista sobre por qué es así. Utilizo en este ejemplo el método de estimación de SizeEstimator de Spark, pero no encontré ninguna falla en su código, así que me pregunto por qué, si proporcionan una buena estimación de la memoria, por qué tengo esto:
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")
La salida de la consola se imprime:
Raw size with doubles: 200
Size with doubles: 96
Raw size with floats: 272
Size with floats: 168
Entonces mi pregunta es bastante ingenua: ¿por qué las carrozas tienden a tomar más memoria que las dobles en este caso? Y ¿por qué empeora cuando lo transformo en un iterador (primer caso, hay una proporción del 75% que se convierte en una proporción del 50% cuando se transforma en un iterador).
(Para tener más contexto, caí en esto al tratar de "optimizar" una aplicación Spark cambiando Double
to Float
y descubrí que en realidad llevaba más memoria teniendo flotantes que dobles ...)
PD: no se debe al tamaño pequeño de los buffers (aquí 3), si pongo 100, obtengo:
Raw size with doubles: 3752
Size with doubles: 3200
Raw size with floats: 6152
Size with floats: 5600
y las carrozas aún consumen más memoria ... Pero la relación se ha estabilizado, por lo que parece que las diferentes proporciones en la transformación a iterador se deben a una sobrecarga, supongo.
EDITAR: parece que Product2
realidad solo está especializado en Int
, Long
y Double
:
trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Double) +T2] extends Any with Product
¿Alguien sabe por qué Float
no se tiene en cuenta? Ni Short
que conduce a comportamientos extraños ...