【问题标题】:why Firefox runs this code 10x faster than Chrome为什么 Firefox 运行此代码的速度比 Chrome 快 10 倍
【发布时间】:2017-02-03 17:15:39
【问题描述】:

我需要在 WebKit 上运行此代码,它是 android 混合应用程序的一部分:

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"

【问题讨论】:

  • 虽然差异较小(8-9 vs 2.5-3 ms),我可以reproduce这个。很有趣。
  • FF 不像 Chrome 那样忙于收集您的元数据?
  • 您想要关于 JavaScript 引擎内部结构的技术解释,还是只是对您的代码进行修复?
  • x_histogram[x] += green; y_histogram[y] += green; 好像很贵
  • @ÁlvaroGonzález,两位,我想修复我的代码,但也有兴趣了解。

标签: javascript v8 spidermonkey


【解决方案1】:

这个快速的 n 脏代码在 v8 中已经明显更快了。 (对于 1000x1000 数据集约 24 毫秒)

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 使其显式。

编辑: 这是我设法在没有不必要的 |0 的情况下获得的最快速度。 500x500 约 4 毫秒,1000x1000 约 11 毫秒。请注意,我反转了循环,因此它按顺序读取数据以利用预取,并且我还使用了更大的数据集以使改进变得明显。

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;
        }
    }
}

【讨论】:

  • 您只需要使用var green = ((g &gt; 80) &amp;&amp; (g &gt; (r + 35)|0) &amp;&amp; (g &gt; (b + 35)|0))|0;|0 的其余部分微不足道。不过,不错的发现。
  • @Cerbrus 你对它进行了基准测试吗?我先尝试了,然后我发现其他人的改进更大|0。
  • 是的,I did|0 仅在该行中与在其他行中的区别非常微不足道。
  • @Cerbrus 是的,我把它们都给了一个快速的答案。
  • @bokan,太棒了!似乎有效的变化是++和i+3。即使调用 is_green 函数也不会增加大量时间。
【解决方案2】:

我来自 2021 年。我目前在 i3 四核 CPU 64 位系统上使用 Chrome 版本 87.0.4280.88 和 Firefox 版本 84.0.2。

我尝试了您的代码,结果是 Chrome 的结果:

这适用于 FireFox:

是的,到目前为止,速度结果非常相似。但作为奖励,我做了一些测试代码:

    console.time("speed test");
    for(let i = 0; i < 100000; i++) {
      console.log(i);
    }
    console.timeEnd("speed test");

结果非常令人惊讶。

铬:2527.755859375 ms

火狐:15687ms

【讨论】:

  • console.log in chrome 没有按顺序输出。在 Firefox 中是这样。
猜你喜欢
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 2015-10-27
相关资源
最近更新 更多