Scalaのインクリッツを介した「ボクシング」プリミティブタイプのオーバーヘッド
-
09-10-2019 - |
質問
Javaのようなクラスが欲しいとします Date
. 。その唯一のデータメンバーは、1970年以来のミリ秒を表す長い長さです。
新しいSCALAタイプを作成するだけのパフォーマンスの利点がありますか:
type PrimitiveDate = Long
次に、Intのために行われているように、暗黙の変換を使用してメソッドを追加できます RichInt
. 。プリミティブタイプの豊かなクラスへのこの「ボクシング」には、オーバーヘッド(クラスの作成)が含まれますか?基本的には、静的な方法だけを用意することができます
def addMonth(date: PrimitiveDate, months: Int): PrimitiveDate = date + 2592000000 * months
そして、タイプシステムに、 d addMonth 5
コード内に表示されます。
編集
書くことで作成するエイリアスのようです type PrimitiveDate = Long
Scalaコンパイラによって強制されていません。適切なクラスを作成し、Scalaで強制されたタイプを作成する唯一の方法である長い方法を囲んでいますか?
プリミティブタイプの強制タイプエイリアスを作成できることはどの程度役立ちますか?
解決
良い、 脱出分析 最新のJVMが実際にあなたを作成する必要がないことを意味するはずです リッチなラッパー 電話するため addMonth
方法。
これにどの程度 実際に実際に発生します 明らかに、ランタイムの量に依存します ホットスポット JVMは、これらの方法がオブジェクト作成に追加されていることを決定します。脱出分析が起こっていない場合、明らかにJVMは(あなたが言うように)「ボックス」する必要があります Long
ラッパークラスの新しいインスタンス。 「クラスの作成」は含まれません。「クラスのインスタンスの作成」が含まれます。この例では、短命であることはすぐにGC-Dになるため、オーバーヘッド(小さな)は次のとおりです。
- インスタンスのメモリ割り当て
- インスタンスのGC-ing
これらは、ガベージの作成を最小限に抑えようとしている非常に低い遅延コードを間違いなく書いている場合、明らかに何らかの問題になるでしょう。これが事実であるかどうかを知っているのはあなただけです。
アプローチがあなたのために機能するかどうか(そして脱出分析があなたの助けになります)、あなたは野生でテストする必要があります。マイクロベンチマークは、この種のことを書くのが難しいことで有名です。
私がこれらのタイプエイリアスがあまり好きではない理由 パブリックAPIの一部であること Scalaは、私が望むほど厳密にそれらを実施していないということです。例えば:
type PrimitiveDate = Long
type PrimitiveSpeed = Long
type Car = String
type Meeting = String
var maxSpeeds : Map[Car, PrimitiveSpeed] = Map.empty
//OOPS - much too easy to accidentally send the wrong type
def setDate(meeting : Meeting, date : PrimitiveDate) = maxSpeeds += (meeting -> date)
他のヒント
指定された例で実際に新しいタイプを作成していません。これは、既存の長いタイプのエイリアスです。
これは、扱いにくいネストされたつながりを扱うために頻繁に使用するテクニックです。たとえば、私は別名です type Grid = Seq[Seq[Int]]
指定する必要がないようにします Seq[Seq[Int]]
さまざまなパラメーターについて何度も何度も。
あなたは非常に幸せに渡すことができます Long
aを取る方法に PrimitiveDate
メソッド、あなたは 行う コードがはるかに自己文書化されているという利点があります。
実際に、タイプセーフティと便利なパターンマッチングを備えた新しいタイプを作成したい場合は、ケースクラスを使用します。
case class PrimitiveDate(value:Long)
そして、潜在的には、利便性のために暗黙のlong => PrimitiveDate変換を提供することさえあります。
この質問をしてから11か月後、Miles Sabinは非常にシンプルでエレガントでパフォーマンスのある作成方法を発見しました ボックス化されていないNewTypes Scalaで。タイプエイリアスとは異なり、タイプタグが施行されます。プリミティブタイプには、専門化を提供するために最小限のボイラープレート(プリミティブごとに1行)が必要です。
1年後、彼はAを追加しました より洗練された堅牢なバージョン これの 形のない. 。コンセプトは、その優れたライブラリの残りの部分を望まない場合、シェイプレスを追加せずにプロジェクトで複製するのに十分なシンプルで簡潔です。
もちろん、あなたとあなたの質問に答えた人々の両方は、おそらくこれを知っているでしょうが、これはまだ重要な質問だからここに追加する価値があります。