assert lento Scala
-
19-09-2019 - |
Domanda
Abbiamo profilatura nostro codice di recente e abbiamo incontrato un paio di hotspot fastidiosi. Sono in forma
assert(a == b, a + " is not equal to " + b)
perché alcuni di questi asserisce può essere in codice chiamato una quantità enorme di volte che la concat stringa inizia a sommare. assert
è definito come:
def assert(assumption : Boolean, message : Any) = ....
perché non è definito come:
def assert(assumption : Boolean, message : => Any) = ....
In questo modo sarebbe valutare pigramente. Dato che non è definito in questo modo c'è un modo in linea di chiamare affermare con un param messaggio che viene valutata pigramente?
Grazie
Soluzione
La valutazione pigra ha anche un certo overhead per l'oggetto funzione creato. Se l'oggetto messaggio è già completamente costruito (un messaggio statico) questo sovraccarico non è necessaria.
Il metodo appropriato per il caso d'uso sarebbe sprintf-style:
assert(a == b, "%s is not equal to %s", a, b)
Fino a quando non v'è una funzione speciaized
assert(Boolean, String, Any, Any)
questa implementazione non appesantisce o il costo della matrice args var
assert(Boolean, String, Any*)
per il caso generale.
toString di attuazione dovranno essere valutata pigramente, ma non è leggibile:
assert(a == b, new { override def toString = a + " is not equal to " + b })
Altri suggerimenti
E 'per nome, ho cambiato più di un anno fa.
http://www.scala-lang.org/node/825
attuale Predef:
@elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed: "+ message)
}
Risposta Thomas' è grande, ma solo nel caso in cui vi piace l'idea di l'ultima risposta, ma non amano l'illeggibilità, è possibile ottenere intorno ad esso:
object LazyS {
def apply(f: => String): AnyRef = new {
override def toString = f
}
}
Esempio:
object KnightSpeak {
override def toString = { println("Turned into a string") ; "Ni" }
}
scala> assert(true != false , LazyS("I say " + KnightSpeak))
scala> println( LazyS("I say " + KnightSpeak) )
Turned into a string
I say Ni
Prova: assert( a==b, "%s is not equals to %s".format(a,b))
Il formato dovrebbe essere chiamato solo quando l'asserzione ha bisogno della stringa. Format viene aggiunto RichString via implicita.