Verwendung von lazy val für die Zwischenspeicherung von Zeichenfolgendarstellungen

7

Ich habe den folgenden Code in JAXMags Scala-Sonderausgabe gefunden:

%Vor%

Bietet die Verwendung von lazy val im obigen Code erheblich mehr Leistung als der folgende Code?

%Vor%

Oder ist es nur eine unnötige Optimierung?

    
user7845123 07.10.2010, 15:21
quelle

5 Antworten

19

Eine Sache, die bei Lazy Vals zu beachten ist, besteht darin, dass sie zwar nur einmal berechnet werden, aber jeder Zugriff auf sie durch einen doppelt überprüften Sperr-Wrapper geschützt ist. Dies ist erforderlich, um zu verhindern, dass zwei verschiedene Threads versuchen, den Wert gleichzeitig mit lustigen Ergebnissen zu initialisieren. Die doppelte Überprüfung ist nun ziemlich effizient (da sie nun in der JVM funktioniert) und erfordert in den meisten Fällen keine Sperrenerfassung, aber es gibt mehr Aufwand als ein einfacher Wertzugriff.

Zusätzlich (und etwas offensichtlich), indem Sie die Zeichenfolgendarstellung Ihres Objekts zwischenspeichern, gehen Sie explizit CPU-Zyklen für möglicherweise große Zunahmen in der Speichernutzung aus. Die Zeichenfolgen in der "def" -Version können Garbage-collected sein, während die in der "lazy val" -Version nicht enthalten sind.

Schliesslich, wie immer bei Leistungsfragen, bedeuten theoriebasierte Hypothesen fast nichts ohne faktenbasiertes Benchmarking. Sie werden nie sicher wissen, ohne Profiling, also könnte es auch versuchen und sehen.

    
Dave Griffith 07.10.2010 15:59
quelle
13

toString kann direkt mit lazy val überschrieben werden.

%Vor%

Beachten Sie, dass eine def eine val nicht überschreiben darf - Sie können nur Mitglieder in der Unterklasse stabiler machen.

    
retronym 07.10.2010 16:16
quelle
1

Im ersten Ausschnitt wird position nur einmal berechnet, bei Bedarf wird die Methode toString aufgerufen. Im zweiten Snippet wird toString body bei jedem Aufruf der Methode erneut ausgewertet. Da x und y nicht geändert werden können, ist es sinnlos, und toString value sollte gespeichert werden.

    
Vasil Remeniuk 07.10.2010 15:39
quelle
0

Fallklassen sind per Definition unveränderbar. Jeder von toString zurückgegebene Wert wird ebenfalls unveränderlich sein. Daher ist es sinnvoll, diesen Wert durch Verwendung eines Lazy Val im Wesentlichen zu "cachen". Auf der anderen Seite führt die bereitgestellte toString-Implementierung wenig mehr als den Standardwert toString aus, der von allen Fallklassen bereitgestellt wird. Ich wäre nicht überrascht, wenn eine Vanilla-Case-Klasse toString ein Lazy Val darunter verwendet.

    
Max A. 07.10.2010 15:38
quelle
0

Sieht für mich wie eine Mikrooptimierung aus. JVM ist in der Lage, sich um solche Fälle zu kümmern.

    
Rayne Smith 07.10.2010 15:58
quelle