2016-09-26 8 views
7

мне нужно, чтобы запустить этот код на WebKit, это часть гибридного приложения для андроид:почему Firefox работает этот код в 10 раз быстрее, чем 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; 
    } 
} 

Вот полный код для теста: https://jsbin.com/boduputebu/edit?js,console

Я думал, что V8 быстрее Firefox (SpiderMonkey), но здесь для этого простого кода SpiderMonkey значительно быстрее. На моем ноутбуке производительность составляет:

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

У вас есть идеи изменить код, чтобы быстро протестировать его на V8. С текущей производительностью я должен был написать ее родной на стороне Java, но это не очень хороший вариант для меня. Или, если нет способа сделать это быстрее, вы знаете, почему V8 работает с этим кодом очень медленнее?

Версия:

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

В то время как разница меньше (8-9 против 2,5-3 мс), могу [воспроизвести] (https://jsbin.com/nexocopuka/1/edit?js,console) это. Интересно. – Cerbrus

+1

FF не занят для сбора ваших метаданных так же, как Chrome? – Teemu

+0

Вы хотите получить техническое объяснение о внутренних механизмах JavaScript или просто исправить свой код? –

ответ

4

Этот быстрый малоэффективный код уже значительно быстрее v8. (~ 24ms для набора данных 1000x1000)

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 гарантировать, что число является целым числом, то asm js техника. Вызов массива с номером требует, чтобы он был целым числом, используя | 0, делает его явным.

EDIT: И это самое быстрое, что мне удается получить без ненужных 0. ~ 4 мс для 500x500 и ~ 11 для 1000x1000. Обратите внимание, что я инвертировал циклы, чтобы он считывал данные в последовательности, чтобы воспользоваться преимущественной выборкой, и я также использовал больший набор данных, чтобы сделать улучшения заметными.

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

Вам нужно использовать только 'var green = ((g> 80) && (g> (r + 35) | 0) && (g> (b + 35) | 0)) | 0;'. Остальная часть '| 0' несущественна. Приятная находка. – Cerbrus

+0

@Cerbrus вы сравнили это? Сначала я попробовал, потом увидел еще большее улучшение с другими | 0. – bokan

+0

Да, [я сделал] (https://jsbin.com/sowohefile/2/edit?js,console). Разница между '| 0' только в этой строке, а также на других линиях - очень незначительна. – Cerbrus