16

我正在编写一个非常繁重的 JavaScript 应用程序(它几乎都是 JavaScript),它确实有大量数据需要迭代(JSON),因此它必须执行某些算术任务。性能是应用程序的主要考虑因素。我已经介绍了 Webworkers 来帮助解决这个问题,并且我试图不依赖于 jQuery 等库提供的方法(比如.each()代替for循环)。无论如何,这是一个简单的问题......

在应用程序中,我必须应用价格变化,这将涉及许多涉及除法的数值过程。记住这会发生成千上万次,对我来说,总是通过乘法或乘法和除法的混合来应用更改会更好。例如,我可以通过乘以 0.5 或除以 2 来应用 50% 的折扣。

我总是被教导除法比乘法慢,但我没有真正的证据……在我开始基准测试和运行测试之前,有人对此有意见吗?

4

3 回答 3

66

尽管这两种操作都非常快,但乘法的性能略好于除法。在我的测试中(如下),我注意到 Chrome 和 IE 9 有 14% 的差异和 10% 的差异。如果您必须从浏览器中压缩性能,您可以在进入循环之前将除法器转换为乘法器,但我没有认为将可读性妥协到如此微小的改进是一个好主意。

var cnt = 500000;
var rls = []
var ags = [[2,1], [4,2], [7,3], [4e0,1], [32e0,2], [37e0,3], [-37e7,(7e3/3e-4)]];
var fns = [
  {name: "fn_mul", fn: (function(x, y) { return x * y; })},
  {name: "fn_div", fn: (function(x, y) { return x / y; })}
]

// setup  ---------------------------------------
for(var iag=0; iag<ags.length; iag++) {
  if(Object.prototype.toString.call(ags[iag]) !== "[object Array]") {
    ags[iag] = [ags[iag]]
  };
}

// run ------------------------------------------
for(var ifn=0; ifn<fns.length; ifn++) {
  var fn = fns[ifn].fn;
  var ts = (new Date()).valueOf();
  for(var iag=0; iag<ags.length; iag++) {
    var ag = ags[iag];
    for(var icn=0; icn<cnt; icn++) { fn.apply(this, ag); }
  }
  rls.push({"name": fns[ifn].name, "ts": (new Date()).valueOf() - ts});
}
dump(rls);
于 2012-05-10T14:47:59.993 回答
8

要为此添加更多上下文,前提是编译器不优化乘法的除法(例如n / 2转换为n * 0.5),乘法总是比除法快。

这是由于 CPU 执行这些操作的方式:

有关x86 的参考,请参阅https://stackoverflow.com/a/1148060/520857fmul (剧透:比 快 2-3 倍fdiv

有关AMD 的参考,请参阅https://stackoverflow.com/a/17883319/520857fmul (剧透:比 快 7 倍fdiv

这些操作的速度太快了,对 IRL 没有影响,但是如果你做了很多,你发现编译器没有转换为乘法(我不认为 javascript 引擎这样做,不要引用我的话不过,快速的谷歌检查并没有给我任何关于这个主题的信息),那么如果你遇到由部门太慢导致的性能瓶颈,那么进行这种优化可能是有意义的,因为你不太可能在几乎所有应用程序中,它可能是 I/O 绑定而不是 CPU 绑定。

编辑:如果您正在执行大量浮点计算,您可以考虑找到一种方法来使用您的 GPU 来执行这些操作,因为 GPU 在 FP 操作上比 CPU 快得多,再次从快速谷歌搜索开始:http //gpu.rocks/

于 2018-09-17T17:13:19.267 回答
0

就个人而言,我认为它在性能方面没有太大区别。如果您正在考虑这一点,那么您将进入微观层面。

代码的可读性比这样的微优化更重要。代码的可读性和易于理解,如果您绝对必须进行微优化,请稍后在您发现真正的瓶颈时进行。

于 2012-05-10T14:03:36.410 回答