To są szczegóły, które udało mi się wykopać. Warto przede wszystkim zauważyć, że chociaż JavaScript jest zwykle uważany za interpretowany i uruchamiany na maszynie wirtualnej, tak naprawdę nie jest tak w przypadku współczesnych interpreterów, które mają tendencję do kompilowania źródła bezpośrednio w kodzie maszynowym (z wyjątkiem IE).
Chrome: silnik V8
V8 ma pamięć podręczną kompilacji. Przechowuje skompilowany JavaScript przy użyciu skrótu źródła dla maksymalnie 5 kolekcji śmieci. Oznacza to, że dwa identyczne fragmenty kodu źródłowego będą współdzielić wpis pamięci podręcznej w pamięci, niezależnie od tego, w jaki sposób zostały uwzględnione. Ta pamięć podręczna nie jest czyszczona po ponownym załadowaniu stron.
Źródło
Aktualizacja - 19.03.2015
Zespół Chrome opublikował szczegółowe informacje na temat swoich nowych technik przesyłania strumieniowego JavaScript i buforowania .
- Streaming skryptu
Strumieniowe przesyłanie skryptów optymalizuje parsowanie plików JavaScript. [...]
Począwszy od wersji 41, Chrome analizuje skrypty asynchroniczne i odroczone w osobnym wątku, gdy tylko pobieranie się rozpocznie. Oznacza to, że parsowanie może zakończyć się zaledwie milisekundy po zakończeniu pobierania, co powoduje, że strony ładują się nawet o 10% szybciej.
- Buforowanie kodu
Zwykle silnik V8 kompiluje kod JavaScript strony przy każdej wizycie, zamieniając go w instrukcje zrozumiałe dla procesora. Ten skompilowany kod jest następnie odrzucany, gdy użytkownik opuści stronę, ponieważ skompilowany kod jest wysoce zależny od stanu i kontekstu maszyny w czasie kompilacji.
Chrome 42 wprowadza zaawansowaną technikę przechowywania lokalnej kopii skompilowanego kodu, dzięki czemu po powrocie na stronę można pominąć pobieranie, analizowanie i kompilowanie. Przy wszystkich ładowaniach stron pozwala to Chrome uniknąć około 40% czasu kompilacji i oszczędza cenną baterię na urządzeniach mobilnych.
Opera: Carakan Engine
W praktyce oznacza to, że za każdym razem, gdy program skryptowy ma zostać skompilowany, którego kod źródłowy jest identyczny z kodem innego programu, który został niedawno skompilowany, ponownie wykorzystujemy poprzednie wyjście kompilatora i całkowicie pomijamy krok kompilacji. Ta pamięć podręczna jest dość skuteczna w typowych scenariuszach przeglądania, w których jedna strona ładuje się strona po stronie z tej samej witryny, takich jak różne artykuły z serwisu informacyjnego, ponieważ każda strona często ładuje tę samą, czasem bardzo dużą bibliotekę skryptów.
Dlatego JavaScript jest buforowany podczas przeładowywania stron, dwa żądania do tego samego skryptu nie spowodują ponownej kompilacji.
Źródło
Firefox: silnik SpiderMonkey
SpiderMonkey używa Nanojit
jako natywnego zaplecza kompilatora JIT. Proces kompilacji kodu maszynowego można zobaczyć tutaj . Krótko mówiąc, wydaje się , że rekompilują skrypty podczas ich ładowania. Jeśli jednak przyjrzymy się bliżej elementom wewnętrznym Nanojit
, zobaczymy, że monitor wyższego poziomu jstracer
, który służy do śledzenia kompilacji, może przechodzić przez trzy etapy podczas kompilacji, zapewniając korzyści Nanojit
:
Początkowy stan monitora śledzenia to monitorowanie. Oznacza to, że spidermonkey interpretuje kod bajtowy. Za każdym razem, gdy spidermonkey interpretuje kod bajtowy skoku do tyłu, monitor odnotowuje liczbę przeskoków do wartości licznika programu skoku docelowego (PC). Ten numer nazywa się liczbą trafień na PC. Jeśli liczba trafień konkretnego komputera osiągnie wartość progową, cel zostanie uznany za gorący.
Gdy monitor zdecyduje, że komputer docelowy jest gorący, szuka w haszcie fragmentów, aby sprawdzić, czy istnieje fragment zawierający natywny kod dla tego komputera docelowego. Jeśli znajdzie taki fragment, przechodzi do trybu wykonywania. W przeciwnym razie przejdzie w tryb nagrywania.
Oznacza to, że dla hot
fragmentów kodu kod macierzysty jest buforowany. Oznacza to, że nie trzeba go ponownie kompilować. Nie jest wyjaśnione, czy te zaszyfrowane sekcje natywne są zachowywane między odświeżeniami strony. Ale przypuszczam, że są. Jeśli ktoś może znaleźć na to dowody potwierdzające, to doskonale.
EDYCJA : Wskazano, że twórca Mozilli Boris Zbarsky stwierdził, że Gecko nie buforuje jeszcze skompilowanych skryptów . Zaczerpnięte z tej SO odpowiedzi .
Safari: JavaScriptCore / SquirelFish Engine
Myślę, że najlepsza odpowiedź na to wdrożenie została już udzielona przez kogoś innego .
Obecnie nie buforujemy kodu bajtowego (ani kodu natywnego). Jest to
opcja, którą rozważaliśmy, jednak obecnie generowanie kodu jest
trywialną częścią czasu wykonywania JS (<2%), więc obecnie nie zajmujemy się
tym.
Napisał to Maciej Stachowiak , główny programista Safari. Myślę więc, że możemy uznać to za prawdę.
Nie udało mi się znaleźć żadnych innych informacji, ale możesz przeczytać więcej na temat poprawy prędkości najnowszego SquirrelFish Extreme
silnika tutaj lub przejrzeć kod źródłowy , jeśli czujesz się odważny.
IE: Silnik czakry
Nie ma aktualnych informacji na temat silnika JavaScript IE9 (czakry) w tym polu. Jeśli ktoś coś wie, prosimy o komentarz.
Jest to dość nieoficjalne, ale w przypadku starszych implementacji silnika IE Eric Lippert ( programista MS JScript ) stwierdza w odpowiedzi na blogu , że:
JScript Classic działa jak język skompilowany w tym sensie, że przed uruchomieniem dowolnego programu JScript Classic w pełni sprawdzamy składnię kodu, generujemy pełne drzewo parsowania i generujemy kod bajtowy. Następnie uruchamiamy kod bajtowy przez interpreter kodu bajtowego. W tym sensie JScript jest tak samo „skompilowany” jak Java. Różnica polega na tym, że JScript nie pozwala na utrwalanie ani sprawdzanie naszego zastrzeżonego kodu bajtowego . Ponadto kod bajtowy jest znacznie wyższy niż kod bajtowy JVM - język kodu bajtowego JScript Classic to niewiele więcej niż linearyzacja drzewa parsowania, podczas gdy kod bajtowy JVM jest wyraźnie przeznaczony do działania na maszynie niskiego poziomu.
Sugeruje to, że kod bajtowy nie utrzymuje się w żaden sposób, a zatem kod bajtowy nie jest buforowany.