2016-02-24 24 views
11

Buraya girdiğim garip bir davranış var ve neden böyle olduğuna dair bir ipucu bulamıyorum. onlar bellek iyi bir tahmin sağlarsanız - - bu yüzden acaba neden bu örnekte estimate method of SizeEstimator from Spark kullanmak ama onların kodunda herhangi bir aksaklık bulamadım ben bu neden:Scala - Neden bu durumda Double Double Floating'ten daha az bellek tüketiyor?

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") 

konsol çıkış baskılar:

Raw size with doubles: 200 
Size with doubles: 96 
Raw size with floats: 272 
Size with floats: 168 

Bu yüzden sorum sorum oldukça naif: Neden bu durumda şamandıralar iki kattan daha fazla bellek alma eğilimindedir? Ve iteratöre dönüştüğümde neden daha da kötüleşiyor (ilk durumda, bir yineleyiciye dönüştürüldüğünde% 50 orana dönüşen% 75'lik bir oran var!).

(daha fazla bağlam sahip olmak, ben ... Float için Double değiştirerek için "optimize" Bir Kıvılcım uygulaması çalışırken bu düştü ve aslında iki katından atlamalara sahip fazla bellek aldığını öğrendim)

PS : Ben 100 koyarsanız o nedeniyle (burada 3) tamponların küçük boyutuna değil bunun yerine alıyorum: görülüyor ki böylece oran stabilize var

Raw size with doubles: 3752 
Size with doubles: 3200 
Raw size with floats: 6152 
Size with floats: 5600 

ve yüzer hala daha fazla bellek tüketir ... Ama Yineleyiciye dönüşümde farklı oranlar, sanırım bazı hava yükü nedeniyle olmalıdır.

DÜZENLEME: Bu Product2 aslında sadece Int, Long ve Double üzerine uzmanlaşmıştır görünüyor: Float dikkate alınmaz neden

trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Double) +T2] extends Any with Product 

kimse biliyor musunuz

? Ne garip davranışlara yol açar Short ...

+0

üzgün sunulacak ise (Int,Double) anlamına

ilkel Java türleri int ve double 2 alanları ile yapı olarak sunulacak Anwer'i göndermeden önce güncellemeyi gör. İsterseniz cevabınızı silebilirim – Odomontois

+0

Cevabınız hayırlı olsun, çünkü neden tüm ilkellerde uzmanlaşmadığını açıklayan bir bağlantı sağladınız! Bu, yol açacağı kombinasyonsal sayıdan kaynaklanıyor ... ki aslında mantıklı geliyor =) Denediğim gibi aptalca bir şekilde optimize etmeye çalışmadan önce bilmek güzel! –

cevap

13

Tuple2Double için @specialized ama Float için özelleşmiş değil olmasıdır. (Int,Float)int ve sargı tipi yapı olarak java.lang.Float alanları

ben değil

fazla tartışma here

+0

Bağlantınızda tuhaf bir şey var, bunun çok fazla uzmanlığa sahip olmak istemedikleri için olduğunu söylüyorlar. Ama kodlara baktığınızda, Product3 bile uzman değil ... Bu yüzden sadece Product1 ve Prodcut2 ... Şamandıralar ve şortlar gibi her zamanki türlerde birkaç uzmanlık kolayca ekleyebilirler! –

+1

@ Vince.Bdn 'Tuple2' genellikle 'Tuple3''den daha sık kullanılır. Bu yüzden daha fazla tanımlamanın kütüphane kavanozuna değmeyeceğine karar verdiler. Etkin mağaza için vaka sınıfları, etkin erişim için [miniboks] (http://scala-miniboxing.org) ve etkin jenerik dönüşümler için [shapeless] (https://github.com/milessabin/shapeless) kullanabilirsiniz. – Odomontois