2016-09-26 36 views
7

trzeba uruchomić ten kod na WebKit, to jest częścią hybrydowego aplikacji dla Androida:dlaczego Firefox uruchamia ten kod 10x szybciej niż Chrome

for(var x = 0; x < width; x++) { 
    for(var y = 0; y < height; y++) { 
     var i = (y * width + x) * 3; 
     var r = data[i]; 
     var g = data[i + 1]; 
     var b = data[i + 2]; 
     var green = is_green(r, g, b); 
     x_histogram[x] += green; 
     y_histogram[y] += green; 
    } 
} 

Oto pełny kod do testu: https://jsbin.com/boduputebu/edit?js,console

Myślałem, że V8 jest szybszy niż Firefox (SpiderMonkey), ale tutaj dla tego prostego kodu SpiderMonkey jest znacznie szybszy. Na moim laptopie wydajność:

Chrome: 30 ms 
Node: 30 ms 
Firefox: 3 ms 
Java (same code with Java): 3 ms 

Czy masz pomysł, aby zmienić kod, aby zrobić to szybko na V8. Przy obecnej wydajności musiałem napisać ją natywnie w Javie, ale nie jest to dla mnie dobra opcja. Lub jeśli nie ma sposobu na przyspieszenie, czy wiesz, dlaczego V8 uruchamia ten kod bardzo wolniej?

Wersja:

Chrome: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36" 
FireFox: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0" 
+0

przy czym różnica jest mniejsza (8-9 vs 2,5-3 ms), mogę [odtworzenia] (https://jsbin.com/nexocopuka/1/edit?js,console) tego produktu. Ciekawy. – Cerbrus

+1

FF nie jest zajęty, aby zbierać dane meta tak samo jak Chrome? – Teemu

+0

Czy potrzebujesz technicznego wyjaśnienia na temat wewnętrznych silników JavaScript lub po prostu poprawki do kodu? –

Odpowiedz

4

Ten szybki n brudny kod jest już znacznie szybciej w V8. (~ 24ms do 1000x1000 zbiorze)

var calc_histogram = function() { 
    for(var x = 0; x < width|0; x++) { 
     for(var y = 0; y < height|0; y++) { 
      var i = ((y * width + x) * 3)|0; 
      var r = data[i]|0; 
      var g = data[i + 1]|0; 
      var b = data[i + 2]|0; 
      var green = ((g > 80) && (g > (r + 35)|0) && (g > (b + 35)|0))|0; 
      x_histogram[x] += green|0; 
      y_histogram[y] += green|0; 
     } 
    } 
}; 

| 0 upewnić się, że liczba ta jest liczbą całkowitą, to asm js technika. Wywołanie tablicy z numerem wymaga, aby upewnić się, że jest liczbą całkowitą, przy pomocy | 0 czyni to wyraźnym.

EDYTOWANIE: I jest to najszybszy możliwy do zdobycia bez zbędnego | 0. ~ 4ms dla 500x500 i ~ 11 dla 1000x1000. Zwróć uwagę, że odwróciłem pętle, aby odczytać dane w kolejności, aby skorzystać z pobierania wstępnego, a także użyłem większego zbioru danych, aby uczynić ulepszenia zauważalnym.

var calc_histogram = function() { 
    var i=0; 
    for(var y = 0; y < height; y++) { 
     for(var x = 0; x < width; x++) { 
      var r = (data[i|0]+35)|0; 
      var g = data[(i+1)|0]; 
      var b = (data[(i+2)|0]+35)|0; 

      if((g > 80) && (g > r) && (g > b)){ 
       x_histogram[x]++; 
       y_histogram[y]++; 
      } 
      i=(i+3)|0; 
     } 
    } 
} 
+0

Należy użyć tylko 'var green = ((g> 80) && (g> (r + 35) | 0) && (g> (b + 35) | 0)) | 0;'. Reszta '| 0' jest nieistotna. Niezłe znalezisko. – Cerbrus

+0

@Cerbrus wykonałeś test porównawczy? Najpierw próbowałem, a potem widziałem jeszcze więcej ulepszeń z innymi | 0. – bokan

+0

Tak, [zrobiłem] (https://jsbin.com/sowohefile/2/edit?js,console). Różnica między '| 0' tylko w tej linii, a gdy jest na innych liniach, jak wel, jest bardzo nieznaczna. – Cerbrus