Quel est l'impact sur les performances de l'utilisation du modèle de classe de type à Scala

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

Question

Je suis actuellement en utilisant largement le modèle de classe de type pour être des parties pertinentes performances de mon code. J'ai fait au moins deux sources potentielles d'inefficacité.

  1. Les paramètres implicites sont transmis le long des appels de message. Je ne sais pas si cela se produit vraiment. Peut-être scalac peut simplement insérer les paramètres implicites où ils sont utilisés et les retirer de la signature de la méthode. Ceci est probablement pas possible dans le cas où vous insérez les paramètres implicites manuellement, car ils pourraient être résolus à l'exécution uniquement. Quelles optimisations ne s'appliquent en ce qui concerne le passage des paramètres implicites

  2. Si l'instance de classe de type est fourni par un def (contrairement à un val), l'objet doit être recréée à chaque invocation d'une « méthode de type classé ». Ce problème peut être par la machine virtuelle Java adressé, ce qui pourrait optimiser la création d'objets loin. Ce problème peut aussi être par scalac par adressé réutilisant ces objets. Quelles optimisations ne sont applicables en ce qui concerne la création d'objets de paramètres implicites?

Et bien sûr, il pourrait y avoir d'autres sources d'inefficacité lors de l'application du modèle de classe de type. S'il vous plaît me dire à leur sujet.

Était-ce utile?

La solution

Si vous vous souciez vraiment à l'écriture de code ultra-haute performance (et vous pouvez que vous faites, mais être très mauvais à ce sujet), puis classes de types vont causer des la douleur pour les raisons suivantes:

  • De nombreux appels supplémentaires méthode virtuelle
  • la boxe probable des primitives (par exemple si vous utilisez des classes de types de scalaz pour monoids etc)
  • créations d'objets via def qui sont nécessaires parce que les fonctions ne peuvent pas être paramétrés
  • créations d'objets pour accéder aux méthodes « souteneur »

Lors de l'exécution, la machine virtuelle Java peut optimiser quelques-unes des créations erronées loin (par exemple la création d'un MA simplement appel <*>), mais scalac ne le fait pas grand-chose à l'aide. Vous pouvez voir cette trivialement en compilant un code qui utilise et en utilisant -Xprint:icode classes de types comme argument.

Voici un exemple:

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

Et voici le 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();
    ()
   }
 }

}

Vous pouvez voir qu'il ya une énorme quantité de création d'un objet qui se passe ici

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top