Domanda

Al momento sto facendo largo uso del modello di classe tipo in essere porzioni di prestazioni rilevanti del mio codice. Ho fatto fuori almeno due potenziali fonti di inefficienza.

  1. I parametri impliciti vengono passati insieme chiamate di messaggi. Non so se questo accade davvero. Forse scalac può semplicemente inserire i parametri impliciti in cui vengono utilizzati e rimuoverli dalla firma del metodo. Questo probabilmente non è possibile nei casi in cui si inseriscono i parametri impliciti manualmente, dal momento che potrebbero essere risolte a tempo di esecuzione solo. Che ottimizzazioni si applicano per quanto riguarda il passaggio di parametri impliciti

  2. Se l'istanza tipo di classe è provvisto da un def (contrariamente a una val), l'oggetto deve essere ricreato ad ogni chiamata di un "metodo digitare classificato". Questo problema può essere destinatari dalla JVM, che potrebbe ottimizzare la creazione di oggetti di distanza. Questo problema potrebbe anche essere destinatari da scalac riutilizzando questi oggetti. Che cosa le ottimizzazioni si applicano per quanto riguarda la creazione di oggetti parametro implicito?

E naturalmente ci potrebbero essere ulteriori fonti di inefficienza quando si applica il modello tipo di classe. Ti prego, dimmi di loro.

È stato utile?

Soluzione

Se avete a cuore veramente a cuore la scrittura di codice ultra-elevate prestazioni (e potrebbe essere pensate che fai, ma essere molto sbagliato su questo) allora typeclasses stanno per causare una certa il dolore per i seguenti motivi:

  • Molte chiamate di metodo virtuali aggiuntivi
  • boxe Probabile primitive (ad esempio se si utilizza typeclasses di scalaz per monoidi etc)
  • creazioni dell'oggetto tramite def necessari perché funzioni possono non essere parametrizzata
  • creazioni di oggetti di accedere al "pimped" metodi

In fase di runtime, la JVM può ottimizzare alcune delle creazioni errate di distanza (per esempio la creazione di un MA semplicemente alla chiamata <*>), ma scalac non fare molto per aiutare. Si può vedere questo banalmente compilando un codice che utilizza typeclasses e utilizzando -Xprint:icode come argomento.

Ecco un esempio:

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

Ed ecco l'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();
    ()
   }
 }

}

Si può vedere c'è una quantità enorme di creazione dell'oggetto succedendo qui

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top