Jedną z przydatnych funkcji Scali jest to lazy val
, że ocena a val
jest opóźniona do momentu, gdy będzie to konieczne (przy pierwszym dostępie).
Oczywiście lazy val
musi mieć pewien narzut - gdzieś Scala musi śledzić, czy wartość została już oszacowana, a ocena musi zostać zsynchronizowana, ponieważ wiele wątków może próbować uzyskać dostęp do wartości po raz pierwszy w tym samym czasie.
Jaki dokładnie jest koszt lazy val
- czy istnieje ukryta flaga logiczna związana z a, lazy val
aby śledzić, czy została oszacowana, czy nie, co dokładnie jest zsynchronizowane i czy są jakieś dodatkowe koszty?
Ponadto załóżmy, że zrobię to:
class Something {
lazy val (x, y) = { ... }
}
Czy to to samo, co posiadanie dwóch oddzielnych lazy val
siatek x
i y
czy otrzymuję narzut tylko raz, dla pary (x, y)
?
źródło
bitmap$0
pole jest niestabilne w obecnej implementacji (2.8).Wygląda na to, że kompilator ustawia pole int mapy bitowej na poziomie klasy, aby oznaczyć wiele leniwych pól jako zainicjowane (lub nie) i inicjuje pole docelowe w zsynchronizowanym bloku, jeśli odpowiedni xor mapy bitowej wskazuje, że jest to konieczne.
Za pomocą:
tworzy przykładowy kod bajtowy:
Wartości zainicjowane w krotkach, takie jak
lazy val (x,y) = { ... }
zagnieżdżone buforowanie za pomocą tego samego mechanizmu. Wynik krotki jest leniwie oceniany i zapisywany w pamięci podręcznej, a dostęp do wartości x lub y wyzwoli ocenę krotki. Wyodrębnianie indywidualnej wartości z krotki jest wykonywane niezależnie i leniwie (i buforowane). Więc powyższy kod dwukrotnie instancji generujex
,y
i jestx$1
polem typuTuple2
.źródło
W Scali 2.10 leniwa wartość, taka jak:
jest kompilowany do kodu bajtowego, który przypomina następujący kod Java:
Zauważ, że mapa bitowa jest reprezentowana przez
boolean
. Jeśli dodasz kolejne pole, kompilator zwiększy rozmiar pola, aby mogło reprezentować co najmniej 2 wartości, tj. Jakobyte
. To dotyczy tylko dużych klas.Ale możesz się zastanawiać, dlaczego to działa? Lokalne pamięci podręczne wątku muszą zostać wyczyszczone podczas wprowadzania zsynchronizowanego bloku, tak aby nieulotna
x
wartość została opróżniona do pamięci. Ten artykuł na blogu zawiera wyjaśnienie .źródło
Scala SIP-20 proponuje nową implementację lazy val, która jest bardziej poprawna, ale ~ 25% wolniejsza niż "aktualna" wersja.
Do proponowanego wprowadzenia wygląda następująco:
Od czerwca 2013 r. Niniejszy SIP nie został zatwierdzony. Spodziewam się, że zostanie on zatwierdzony i włączony do przyszłej wersji Scali na podstawie dyskusji na liście mailingowej. W związku z tym myślę, że mądrze byłoby wziąć pod uwagę obserwację Daniela Śpiewaka :
źródło
Napisałem post w tej sprawie https://dzone.com/articles/cost-laziness
Krótko mówiąc, kara jest tak niewielka, że w praktyce można ją zignorować.
źródło
biorąc pod uwagę kod bycode generowany przez scala dla leniwych, może wystąpić problem z bezpieczeństwem wątków, jak wspomniano w blokowaniu podwójnego sprawdzenia http://www.javaworld.com/javaworld/jw-05-2001/jw-0525-double.html?page=1
źródło