pim*_*vdb 19 javascript optimization google-chrome v8 inline
我想知道是否有可能获得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);
};
})();
Run Code Online (Sandbox Code Playgroud)
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);
};
})();
Run Code Online (Sandbox Code Playgroud)
3.使用文字数字并动态计算常数.
var test3 = (function() {
return function(x) {
return Math.sin(x * 3.141592653589793 / 180);
};
})();
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,结果如下:
test1 - 25,090,305 ops/sec
test2 - 16,919,787 ops/sec
test3 - 16,919,787 ops/sec
Run Code Online (Sandbox Code Playgroud)
它看起来像pi没有得到内联在test2为test2和test3导致量是相同的每秒操作的.
另一方面,划分似乎没有被优化(即预先计算),因为test1明显更快.
小智 7
对第一个问题进行有根据的猜测:
严格来说,它不能对pi / 180零件进行常数折叠,因为你没有pi / 180在第二和第三个函数中做.你刚才划分(x * pi)的180(乘法的优先级).
现在,您可能会问为什么它不会改变操作的顺序以最终可以优化(此过程称为重新关联,顺便说一下)......毕竟,结果是等效的(a * b / c = (a * b) / c).数学如此说,对吧?
好吧,数学说的是,但数学不使用浮点数.随着花车,事情变得更加复杂.x * pi可以舍入,然后重新排序将导致不同的结果.错误可能很小,但仍然是编译器优化的主要规则是:你不能改变程序的结果.在一些数学基准测试中,以一种不幸的方式执行,而不是在一些图形代码中被像素关闭(是的,这可能是显而易见的),这样做会更好.