V8到底是如何优化/内联的?
我想知道是否有可能了解 V8 到底如何优化和内联事物。
我创建了三个简单的测试函数,它们都计算角度的正弦值(以度为单位)。我将它们全部放入闭包中,以便 V8 应该能够内联局部变量。
1. 使用预先计算的常数Math.PI / 180
,然后执行Math.sin(x *constant)
。
我使用了这段代码:
var test1 = (function() {
var constant = Math.PI / 180; // only calculate the constant once
return function(x) {
return Math.sin(x * constant);
};
})();
2. 即时计算常量。
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);
};
})();
3. 使用文字数字并即时计算常量。
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
和 test3
结果内联在 test2
中每秒的操作量完全相同。
另一方面,除法似乎没有被优化(即预先计算),因为 test1
明显更快。
- 如果在这种情况下不手动计算常数,为什么不预先计算常数?
- 是否可以看到V8在某个网页上到底是如何优化功能的?
I'm wondering whether it is possible to get knowledge of how exactly V8 optimizes and inlines things.
I created three simple test functions which all calculate the sine of a angle in degrees. I put them all into closures so that V8 should be able to inline the local variables.
1. Using a precalculated constant Math.PI / 180
, and then do Math.sin(x * constant)
.
I used this code:
var test1 = (function() {
var constant = Math.PI / 180; // only calculate the constant once
return function(x) {
return Math.sin(x * constant);
};
})();
2. Calculating the constant on the fly.
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);
};
})();
3. Using literal numbers and calculating the constant on the fly.
var test3 = (function() {
return function(x) {
return Math.sin(x * 3.141592653589793 / 180);
};
})();
Suprisingly, the results were as follows:
test1 - 25,090,305 ops/sec
test2 - 16,919,787 ops/sec
test3 - 16,919,787 ops/sec
It looks like pi
did get inlined in test2
as test2
and test3
result in exactly the same amount of operations per second.
On the other hand, the division does not seem to be optimized (i.e. precalculated), since test1
is significantly faster.
- Why is the constant not precalculated if you don't do so manually in this case?
- Is it possible to see how V8 exactly optimizes functions on a certain webpage?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对你的第一个问题的有根据的猜测:
严格来说,它不能不断折叠 pi / 180 部分,因为你在第二个问题中不执行 pi / 180 部分和第三个功能。您只需将
(x * pi)
除以180
(乘法优先)。现在,您可能会问为什么它不改变操作顺序以得到可以优化的结果(顺便说一句,这个过程称为重新关联)...毕竟,结果是等效的(
a * b / c = (a * b) / c )。数学是这么说的,对吗?
嗯,数学是这么说的,但数学不使用浮点数。对于浮动,事情变得更加复杂。
x * pi
可能会被舍入,然后重新排序会导致不同的结果。错误可能很小,但编译器优化的主要规则仍然是:您不得更改程序的结果。在一些以不幸的方式编写的数学基准上执行次优要好于在某些图形代码中偏离一个像素(是的,这可能很明显)。An educated guess at your first question:
Strictly speaking, it can't constant-fold the
pi / 180
part, because you don't dopi / 180
in the second and third function. You just divide(x * pi)
by180
(the multiplication has precedence).Now, you may be asking why it doesn't change the order of operations to wind up with something it can optimize (this process is called reassociation, by the way)... after all, the result is equivalent (
a * b / c = (a * b) / c
). Math says so, right?Well, math says so, but math doesn't use floating point numbers. With floats, things are more complicated.
x * pi
may be rounded, and then the reordering would lead to a different result. The errors will probably be tiny, but still, the leading rule of compiler optimization is: Thou must not change the program's outcome. It's better to perform suboptimal on a few math benchmarks written in an unfortunate way than being off by a pixel (yes, that may be noticeable) in some graphics code.要回答你的第二个问题,你可以看到V8使用这个工具优化你的JS的字节码: http://mrale .ph/irHydra/2/ .它非常适合在 Chrome 中进行低级代码调整。
To answer your second question, you can see the bytecode that V8 optimized your JS to using this tool: http://mrale.ph/irhydra/2/ . It's fantastic for low-level tuning of code in Chrome.