Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript V8到底是如何优化/内联的?_Javascript_Optimization_Google Chrome_Inline_V8 - Fatal编程技术网

Javascript V8到底是如何优化/内联的?

Javascript V8到底是如何优化/内联的?,javascript,optimization,google-chrome,inline,v8,Javascript,Optimization,Google Chrome,Inline,V8,我想知道是否有可能了解V8是如何优化和内联的 我创建了三个简单的函数,它们都以度为单位计算角度的正弦。我将它们全部放入闭包中,以便V8能够内联局部变量 一,。使用预先计算的常数Math.PI/180,然后执行Math.sin(x*常数) 我使用了以下代码: var test1 = (function() { var constant = Math.PI / 180; // only calculate the constant once return function(x) {

我想知道是否有可能了解V8是如何优化和内联的

我创建了三个简单的函数,它们都以度为单位计算角度的正弦。我将它们全部放入闭包中,以便V8能够内联局部变量


一,。使用预先计算的常数
Math.PI/180
,然后执行
Math.sin(x*常数)

我使用了以下代码:

var test1 = (function() {
  var constant = Math.PI / 180; // only calculate the constant once

  return function(x) {
    return Math.sin(x * constant);
  };
})();

二,。动态计算常数

var test2 = (function() {
  var pi = Math.PI; // so that the compiler knows pi cannot change
                    // and it can inline it (Math.PI could change
                    // at any time, but pi cannot)

  return function(x) {
    return Math.sin(x * pi / 180);
  };
})();
var test3 = (function() {
  return function(x) {
    return Math.sin(x * 3.141592653589793 / 180);
  };
})();

三,。使用文字数字并动态计算常量

var test2 = (function() {
  var pi = Math.PI; // so that the compiler knows pi cannot change
                    // and it can inline it (Math.PI could change
                    // at any time, but pi cannot)

  return function(x) {
    return Math.sin(x * pi / 180);
  };
})();
var test3 = (function() {
  return function(x) {
    return Math.sin(x * 3.141592653589793 / 180);
  };
})();

令人惊讶的是,结果如下:

test1 - 25,090,305 ops/sec
test2 - 16,919,787 ops/sec
test3 - 16,919,787 ops/sec
看起来,
pi
确实在
test2
中内联,因为
test2
test3
每秒的操作量完全相同

另一方面,由于
test1
的速度明显更快,因此划分似乎没有得到优化(即预先计算)

  • 在这种情况下,如果不手动计算,为什么不预先计算常数
  • 是否有可能看到V8如何精确地优化某个网页上的功能

对你的第一个问题进行有根据的猜测:

严格来说,它不能常数折叠
pi/180
部分,因为在第二个和第三个函数中没有执行
pi/180
。您只需将
(x*pi)
除以
180
(乘法具有优先权)

现在,你可能会问,为什么它不改变操作顺序,最终得到它可以优化的东西(顺便说一句,这个过程叫做重新关联)。。。毕竟,结果是等价的(
a*b/c=(a*b)/c
)。数学是这么说的,对吗


数学是这么说的,但数学不使用浮点数。有了浮动,事情就更复杂了
x*pi
可以四舍五入,然后重新排序将导致不同的结果。错误可能很小,但编译器优化的首要规则是:你不能改变程序的结果。与其在某些图形代码中偏离一个像素(是的,这可能很明显),不如在一些以不幸的方式编写的数学基准上执行次优测试。

要回答第二个问题,您可以看到V8使用此工具优化JS的字节码:。在Chrome中对代码进行低级调优非常棒。

我不确定C风格内联的概念是否适用于JIT虚拟机。我只是在猜测,但我怀疑V8会将运行时优化应用于经常调用的函数,但这可能很难预测。@mikerobi:这可能是一个幼稚的问题-但难道不可能像某种调试工具那样简单地看到V8在编译/优化/内联过程中做了什么吗,但是我怀疑V8开发团队之外的任何人都能告诉你怎么做。例如,PyPy的JIT有大量的日志记录,他们开始构建一个工具来查看代码所经过的所有中间表示(Python字节码、JIT IR、机器码),因此理论上这些事情应该是可能的。但我想这是因为(1)实际的JIT是机器生成的,(2)它是跟踪JIT。V8目前不执行常量传播。另外,通过在循环中创建函数来惩罚V8(多次调用setup):请尝试修改后的测试用例。它消除了对新生成的闭包实例进行多次重新优化所带来的开销,并使情况更加清晰。旁注:如果有人怀疑我关于函数将给出不同结果的说法,请使用
x=0.6784993546113602
,例如。我用
Math.random()
找到了这个和许多其他数字。谢谢,这很有趣。这有助于进行更多的研究(比如使用一个常数
(a*b)*x
)。使用
pi*180*x
确实会产生不同的结果-现在
test1
test3
是相等的,但是
test2
已经变慢了。我认为这可以用操作程序来解释。我将尝试在
test2
中搜索
pi
不再内联的原因。在这种情况下,
x*(pi/180)
给出了什么?理论上,编译器现在可以拉出
pi/180
。@cWalves:当我将我的初始测试与添加括号的同一测试进行比较时,似乎没有什么改进:和。这意味着浮点/运算符优先级的概念实际上不适用。神秘的。。。