13

Testowałem wydajność (z chromowaną linią czasu) w przypadkach, gdy zmienna zdefiniowana jest w zamknięciu. Więc wartości nie byłyby wystawione na użytkownika.Tajemnica profilowania JavaScript - zmienne zamknięcia

Zgodnie z oczekiwaniami run_proto_fn uruchamiać kilka razy szybciej przy minimalnym zbieraniu śmieci i małej ilości pamięci.

Jednak w rzeczywistości run_proto_obj stało się dokładnie odwrotnie, tak jakby kosztowne było posiadanie wartości niefunkcjonalnych w właściwościach właściwości prototypu obiektu.

Czy ktoś może mieć tutaj pewną jasność?

SOME = function(){}; 
 
SOME.prototype.exe = function(v){ 
 
\t var x = { 
 
\t \t a:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?', 
 
\t \t b:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?', 
 
\t \t c:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?', 
 
\t }; 
 
\t return x[v]; 
 
}; 
 

 
SOME2 = function(){}; 
 
SOME2.prototype.exe = function(v){ 
 
\t return this.exes[v]; 
 
}; 
 
SOME2.prototype.exes = { 
 
\t a:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?', 
 
\t b:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?', 
 
\t c:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?', 
 
}; 
 
SOME_FN = function(){}; 
 
SOME_FN.prototype.exe = function(v){ 
 
\t var x = { 
 
\t \t a: function(p){this.p1 = p;return this;}, 
 
     b:function(p){this.p2 = p*3;return this;}, 
 
     c:function(p){this.p3 = p*99;return this;}, 
 
    }; 
 
    return x[v].call(this,42); 
 
}; 
 

 
SOME_FN2 = function(){}; 
 
SOME_FN2.prototype.exe = function(v){ 
 
    return this.exes[v].call(this,42); \t 
 
}; 
 
SOME_FN2.prototype.exes = { 
 
    a: function(p){this.p1 = p;return this;}, 
 
    b:function(p){this.p2 = p*3;return this;}, 
 
    c:function(p){this.p3 = p*99;return this;}, 
 
}; 
 

 
var a1 = a2 = a_fn1 = a_fn2 = []; 
 
\t 
 

 
var run_local_obj = function(){ 
 
\t for (var i = 1000000 - 1; i >= 0; i--) { 
 
\t \t x1 = new SOME(); 
 
\t \t x1.exe('a'); 
 
\t \t a1.push(x1); 
 
\t } 
 
}; 
 
var run_proto_obj = function(){ 
 
\t for (var i = 1000000 - 1; i >= 0; i--) { 
 
\t \t x2 = new SOME2(); 
 
\t \t x2.exe('a'); 
 
\t \t a2.push(x2); 
 
\t } 
 
}; 
 
var run_local_fn = function(){ 
 
\t for (var i = 1000000 - 1; i >= 0; i--) { 
 
\t \t x1 = new SOME_FN(); 
 
\t \t x1.exe('a'); 
 
\t \t x1.exe('b'); 
 
\t \t x1.exe('c'); 
 
\t \t a_fn1.push(x1); 
 
\t } 
 
}; 
 
var run_proto_fn = function(){ 
 
\t for (var i = 1000000 - 1; i >= 0; i--) { 
 
\t \t x2 = new SOME_FN2(); 
 
\t \t x2.exe('a'); 
 
\t \t x2.exe('b'); 
 
\t \t x2.exe('c'); 
 
\t \t a_fn2.push(x2); 
 
\t } 
 
};
<button onclick="run_local_obj(this)">local obj</button> 
 
<button onclick="run_proto_obj(this)">proto obj</button> 
 
<button onclick="run_local_fn(this)">local obj FN</button> 
 
<button onclick="run_proto_fn(this)">proto obj</button>


Słyszałem frazę:

zamknięcie zmienna jest zdefiniowana za każdym razem, że funkcja działa

ale wciąż I'ts mglisty .

+3

Po prostu uruchomiłem oba i nie widziałem żadnych sporej różnicy. Czy odświeżyłeś stronę przed uruchomieniem drugiego testu? Jeśli nie, zwiększysz rozmiar "a1" i "a2" (ponieważ są to te same tablice) do wielkości około 2000000, które mogą być źródłem rozbieżności. –

Odpowiedz

12

Próbowałem uruchomić pomiary i najpierw zauważyłem, że trudno jest zrozumieć, co się dzieje po prostu używając kodu z twojego pytania.

Jeśli przeprowadzę te testy jeden po drugim (klikając przyciski i patrząc na oś czasu), to dla każdego następnego uruchomienia wyniki będą się znacznie różnić. Z kilku przebiegów wyglądało to tak, jakby trzecie (run_local_fn) jest zwykle dłuższe niż inne.

Potem próbowałem uruchomić je w kolejności wstecznej (przyciski od 4 do 1) i otrzymałem zupełnie inny wynik - najdłuższy był model run_local_obj.

Więc trochę zmodyfikowałem kod testowy, aby uzyskać stabilne wyniki.

Pełny kod is here, możesz sklonować repozytorium i przetestować je lokalnie.

Oto jak uruchomić każdy test w Chrome (I uruchomił go za pomocą python -m SimpleHTTPServer 8082 wewnątrz folderu js-perf-test):

  • otworzyć zakładkę z http://localhost:8082/perf.html, otwarte narzędzia dev
  • Rozpocznij harmonogram nagrywania
  • Kliknij przycisk
  • Poczekaj na wyniki w konsoli (min./maks./Średnie).
  • Zatrzymaj nagrywanie na osi czasu

Wyniki są stabilne i powtarzalne (oba czasy i widok timeline), tutaj jest jeden z testów:

Więc co widzimy tutaj to:

1) run_proto_obj jest najszybszy i run_local_obj jest blisko niego.

Sądzę, że oczekiwane jest, aby run_proto_obj był najbardziej wydajny, ponieważ używa statycznie zdefiniowanego obiektu z ciągami. Silnik JS jest prawdopodobnie w stanie zoptymalizować run_local_obj, więc obiekt x jest ponownie używany i nie jest tworzony za każdym razem.

2) Numer run_local_fn jest najwolniejszy.

Tutaj mamy lokalny obiekt x obliczanie obiektów i dynamicznych ciągów, więcej części floating niż w innych testach.

3) Numer run_proto_fn jest szybszy niż run_local_fn, ale wolniejszy od pierwszych dwóch funkcji.

Myślę, że jest to również oczekiwane, obiekt z a, b, c jest zdefiniowany tylko raz (więc jest szybszy niż run_local_fn).

W porównaniu do pierwszych dwóch funkcji dynamicznie oblicza wynikowe ciągi, więc jest wolniejszy.

Wracając do twojego pytania:

Zgodnie z oczekiwaniami run_proto_fn uruchomić kilka razy szybciej i przy minimalnych zbiorów śmieci i niski sterty pamięci. Ale run_proto_obj stało się dokładnie przeciwne, tak jakby kosztowne było posiadanie wartości niefunkcyjnych w właściwościach właściwości prototypu obiektu.

Wygląda na to, że po prostu nie przeprowadziłeś poprawnie eksperymentu. Zgodnie z powyższymi wynikami, run_proto_obj jest w rzeczywistości najszybszy.

Update: Właśnie próbowałem ten sam test w Firefoksie, wyniki są podobne:

  • `run_local_obj '- 344.85ms
  • ` run_proto_obj' - 151.47ms
  • `run_local_fn” - 788.08ms
  • `run_proto_fn” - 265.21ms

run_proto_obj jest najszybszy i run_local_fn jest powolny est.