这一切都很有趣,而且有一个事实,coffee 脚本不能比完全优化的 javascript 运行得更快。
也就是说,因为咖啡脚本正在生成 javascript。有办法让它变得值得。可悲的是,它似乎还不是这样。
举个例子:
new_way = -> [0..1000000]
new_way()
它使用咖啡脚本 1.6.2 编译为此
// Generated by CoffeeScript 1.6.2
(function() {
var new_way;
new_way = function() {
var _i, _results;
return (function() {
_results = [];
for (_i = 0; _i <= 1000000; _i++){ _results.push(_i); }
return _results;
}).apply(this);
};
new_way();
}).call(this);
而clockworkgeek提供的代码是
function oldway()
{
var a = [];
for (var i = 0; i <= 1000000; i++)
a[i] = i;
return a;
}
oldway()
但是由于咖啡脚本将函数隐藏在范围内,我们也应该为 javascript 这样做。我们不想污染窗口对吧?
(function() {
function oldway()
{
var a = [];
for (var i = 0; i <= 1000000; i++)
a[i] = i;
return a;
}
oldway()
}).call(this);
所以这里我们的代码实际上做同样的事情。然后我们想实际测试这两个版本几次。
咖啡脚本
for i in [0..100]
new_way = -> [0..1000000]
new_way()
生成的JS,你可能会问自己那里发生了什么???无论出于何种原因,它都会创建i 和_i。从这两个中我很清楚,只需要一个。
// Generated by CoffeeScript 1.6.2
(function() {
var i, new_way, _i;
for (i = _i = 0; _i <= 100; i = ++_i) {
new_way = function() {
var _j, _results;
return (function() {
_results = [];
for (_j = 0; _j <= 1000000; _j++){ _results.push(_j); }
return _results;
}).apply(this);
};
new_way();
}
}).call(this);
所以现在我们要更新我们的 Javascript。
(function() {
function oldway()
{
var a = [];
for (var i = 0; i <= 1000000; i++)
a[i] = i;
return a;
}
var _i;
for(_i=0; _i <= 100; ++_i) {
oldway()
}
}).call(this);
所以结果:
time coffee test.coffee
real 0m5.647s
user 0m0.016s
sys 0m0.076s
time node test.js
real 0m5.479s
user 0m0.000s
sys 0m0.000s
js 需要
time node test2.js
real 0m5.904s
user 0m0.000s
sys 0m0.000s
所以你可能会问自己......什么地狱咖啡脚本更快???然后您查看代码并问自己...所以让我们尝试修复它!
(function() {
function oldway()
{
var a = [];
for (var i = 0; i <= 1000000; i++)
a.push(i);
return a;
}
var _i;
for(_i=0; _i <= 100; ++_i) {
oldway()
}
}).call(this);
然后我们将对 JS 脚本做一个小修复并将 a[i] = i 更改为 a.push(i) 然后让我们再试一次...然后 BOOM
time node test2.js
real 0m5.330s
user 0m0.000s
sys 0m0.000s
这个小改动让它比我们的 CoffeeScript 更快 现在让我们看看生成的 CoffeeScript...并删除那些双变量...
对此:
// Generated by CoffeeScript 1.6.2
(function() {
var i, new_way;
for (i = 0; i <= 100; ++i) {
new_way = function() {
var _j, _results;
return (function() {
_results = [];
for (_j = 0; _j <= 1000000; _j++){ _results.push(_j); }
return _results;
}).apply(this);
};
new_way();
}
}).call(this);
和繁荣
time node test.js
real 0m5.373s
user 0m0.000s
sys 0m0.000s
我想说的是,使用高级语言有很多好处。生成的 CoffeeScript 没有经过优化。但是离纯js代码不远了。 clockworkgeek 尝试直接使用 index 而不是 push 的代码优化实际上似乎适得其反,并且比生成的咖啡脚本运行得更慢。
这种优化很难找到和修复的事实。另一方面,从版本到版本,coffeescript 可以为当前浏览器或解释器生成优化的 js 代码。 CoffeeScript 将保持不变,但可以再次生成以加快速度。
如果您直接用 javascript 编写代码,现在可以像使用真正的编译器一样优化代码。
另一个有趣的部分是有一天,CoffeeScript 或其他 javascript 生成器可用于分析代码(如 jslint)并删除不需要某些变量的部分代码...使用不同的参数以不同的方式编译函数在不需要某些变量时加快速度。如果您有 purejs,则必须期望有一个 JIT 编译器可以正确完成工作,并且对咖啡脚本也有好处。
例如,我可以最后一次优化咖啡脚本......通过从 for 循环中删除 new_way = (function...。一位聪明的程序员会知道,这里唯一发生的事情就是在每个循环上重新影响函数,这不会改变变量。该函数是在函数范围内创建的,并且不会在每个循环中重新创建。那就是说它不应该有太大变化......
time node test.js
real 0m5.363s
user 0m0.015s
sys 0m0.000s
差不多就是这样。