2016-02-24 11 views
11

ここに私が陥った奇妙な振る舞いがあります。なぜこれがこのようなのかのヒントは見つかりません。私は、この例ではestimate method of SizeEstimator from Sparkを使用しますが、私はそう自分のコード内の任意のグリッチを発見していないなぜだろうか - 彼らはメモリの良い推定を提供する場合 - 私はこれ持っている理由:Scala - なぜDoubleはこの場合Floatより少ないメモリを消費しますか?

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 

私の質問は非常に素朴です:浮動小数点はなぜこの場合ダブルスよりも多くのメモリを取る傾向がありますか?そして、イテレータに変換すると、それがさらに悪化するのはなぜですか(最初のケースでは、イテレータに変換すると50%の比率になる75%の比率があります)。

(より多くのコンテキストを持っているために、私は... FloatDoubleを変更することによって、「最適化」スパークアプリケーションをしようとしたときに、このに落ち、それが実際に倍以上山車を持つより多くのメモリを取ったことが判明)

PS :それは、バッファのサイズが小さいのせいではないのです(ここでは3)私が代わりに100を入れた場合、私が取得:

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

、まだ多くのメモリを消費浮かぶ...しかし、比率が安定しているので、それがいるようですイテレータへの変換における異なる比率は、私が推測するいくつかのオーバーヘッドのためでなければなりません。

EDIT:Product2は実際にのみIntLongDoubleに特化されているようだ:

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

Floatを考慮しない理由を誰もが知っていますか?どちらの奇妙な行動につながるShort ...

+0

申し訳ありませんが提示される一方で(Int,Double)を意味

は、プリミティブJava型intdoubleの2つの分野で構造体として提示されますanwerを掲示する前にアップデートを見ないでください。もしあなたが望むのであれば、私は答えを削除することができます – Odomontois

+0

あなたはすべてのプリミティブに特化していない理由を説明したリンクを提供してくれたので、それは、それが導くコンビナトリアルナンバーによるものです...実際には理にかなっています=)私は試したように愚かに最適化しようとする前に知っておきましょう! –

答えて

13

Tuple2Doubleため@specializedですがFloatに特化していないためです。 (Int,Float)intとラッパー型と構造体としてjava.lang.Floatフィールド

私はdidnの

もっと議論here

+0

あなたのリンクには何か変わったことがありますが、それはあまりにも多くのスペシャライゼーションを望んでいないからだと言います。しかし、コードを見ると、Product3は特殊化されていません...だから、Product1とProdcut2だけです...普通のタイプのいくつかの特殊化を浮動小数点として簡単に追加できました! –

+1

@ Vince.Bdn 'Tuple2'は' Tuple3'より頻繁に使用されます。だから私は、彼らはライブラリのjarサイズに値するものではないというさらなる定義を決めたと思います。効率的なアクセスのための効果的なストア[miniboxing](http://scala-miniboxing.org)と効率的な一般的な変換のための[shapeless](https://github.com/milessabin/shapeless)のケースクラスを使うことができます – Odomontois

関連する問題