Scalaでタイプクラスパターンを使用することのパフォーマンスへの影響は何ですか

StackOverflow https://stackoverflow.com/questions/9327465

質問

私は現在、私のコードのパフォーマンスに関連する部分になるために、タイプクラスのパターンを広範囲に使用しています。私は少なくとも2つの潜在的な非効率性源を作りました。

  1. 暗黙のパラメーターは、メッセージ呼び出しに沿って渡されます。これが本当に起こるかどうかはわかりません。 Scalacは、使用されている場所に暗黙のパラメーターを挿入して、メソッドの署名からそれらを削除するだけかもしれません。これは、実行時にのみ解決される可能性があるため、暗黙のパラメーターを手動で挿入する場合にはおそらく不可能です。 暗黙的なパラメーターを渡すことに関して、最適化が適用されるもの?

  2. タイプクラスインスタンスがaによって提供されている場合 def (aに反して val)、オブジェクトは、「タイプ分類されたメソッド」の呼び出しごとに再作成する必要があります。この問題は、オブジェクトの作成を最適化する可能性のあるJVMによって称賛される可能性があります。この問題は、これらのオブジェクトを再利用することにより、Scalacによって引き渡される可能性があります。 暗黙のパラメーターオブジェクトの作成に関して、どのような最適化が適用されますか?

そしてもちろん、タイプクラスパターンを適用する際には、追加の非効率性の発生源があるかもしれません。それらについて教えてください。

役に立ちましたか?

解決

あなたが本当に超高性能コードを書くことを本当に気にしているなら(そしてあなたは 考える あなたはそうします 大きな過ち これについて)次の理由でタイプクラスは痛みを引き起こすでしょう。

  • 多くの追加の仮想メソッド呼び出し
  • プリミティブの可能性のあるボクシング(例えば、モノイドなどにScalazのタイプクラスを使用する場合)
  • 経由のオブジェクト作成 def 関数をパラメーター化できないため、これが必要です
  • オブジェクトの作成「Pimped」メソッドにアクセスします

実行時に、JVMは誤った作品の一部を最適化する場合があります(例: MA 単に電話するだけです <*>)、 しかし scalac 助けるためにあまりしません。タイプクラスを使用して使用するコードをコンパイルして使用することで、これを簡単に見ることができます -Xprint:icode 議論として。

これが例です:

import scalaz._; import Scalaz._
object TC {
  def main(args: Array[String]) {
    println((args(0).parseInt.liftFailNel |@| args(1).parseInt.liftFailNel)(_ |+| _))
  }
}

そして、これがicodeです:

final object TC extends java.lang.Object with ScalaObject {
  def main(args: Array[java.lang.String]): Unit = scala.this.Predef.println(scalaz.this.Scalaz.ValidationMA(scalaz.this.Scalaz.StringTo(args.apply(0)).parseInt().liftFailNel()).|@|(scalaz.this.Scalaz.StringTo(args.apply(1)).parseInt().liftFailNel()).apply({
  (new anonymous class TC$$anonfun$main$1(): Function2)
}, scalaz.this.Functor.ValidationFunctor(), scalaz.this.Apply.ValidationApply(scalaz.this.Semigroup.NonEmptyListSemigroup())));
def this(): object TC = {
  TC.super.this();
  ()
}
};
@SerialVersionUID(0) final <synthetic> class TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$2 extends scala.runtime.AbstractFunction0 with Serializable {
  final def apply(): Int = TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$2.this.v1$1;
  final <bridge> def apply(): java.lang.Object = scala.Int.box(TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$2.this.apply());
  <synthetic> <paramaccessor> private[this] val v1$1: Int = _;
  def this($outer: anonymous class TC$$anonfun$main$1, v1$1: Int): anonymous class TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$2 = {
    TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$2.this.v1$1 = v1$1;
    TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$2.super.this();
    ()
  }
};
@SerialVersionUID(0) final <synthetic> class TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1 extends scala.runtime.AbstractFunction0$mcI$sp with Serializable {
  final def apply(): Int = TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1.this.apply$mcI$sp();
  <specialized> def apply$mcI$sp(): Int = TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1.this.v2$1;
  final <bridge> def apply(): java.lang.Object = scala.Int.box(TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1.this.apply());
  <synthetic> <paramaccessor> private[this] val v2$1: Int = _;
  def this($outer: anonymous class TC$$anonfun$main$1, v2$1: Int): anonymous class TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1 = {
    TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1.this.v2$1 = v2$1;
   TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1.super.this();
  ()
  }
};
@SerialVersionUID(0) final <synthetic> class TC$$anonfun$main$1 extends scala.runtime.AbstractFunction2$mcIII$sp with Serializable {
  final def apply(x$1: Int, x$2: Int): Int = TC$$anonfun$main$1.this.apply$mcIII$sp(x$1, x$2);
  <specialized> def apply$mcIII$sp(v1$1: Int, v2$1: Int): Int = scala.Int.unbox(scalaz.this.Scalaz.mkIdentity({
(new anonymous class TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$2(TC$$anonfun$main$1.this, v1$1): Function0)
}).|+|({
    (new anonymous class TC$$anonfun$main$1$$anonfun$apply$mcIII$sp$1(TC$$anonfun$main$1.this, v2$1): Function0)
}, scalaz.this.Semigroup.IntSemigroup()));
final <bridge> def apply(v1: java.lang.Object, v2: java.lang.Object): java.lang.Object = scala.Int.box(TC$$anonfun$main$1.this.apply(scala.Int.unbox(v1), scala.Int.unbox(v2)));
  def this(): anonymous class TC$$anonfun$main$1 = {
    TC$$anonfun$main$1.super.this();
    ()
   }
 }

}

あなたはここで膨大な量のオブジェクト作成が起こっていることがわかります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top