coffeescript比javascript快吗?

coffeescript比javascript快吗?,javascript,performance,html,coffeescript,benchmarking,Javascript,Performance,Html,Coffeescript,Benchmarking,Javascript无处不在,在我看来,它越来越重要。大多数程序员都会同意,虽然Javascript本身很难看,但它的“领域”的确令人印象深刻。凭借HTML5的功能和现代浏览器通过Javascript部署应用程序的速度,这是一个有趣的选择:它可能是跨平台的 自然的结果是交叉编译器。主要的可能是GWT,但还有其他几种选择。我最喜欢的是Coffeescript,因为它只在Javascript上添加了一层薄薄的内容,并且比例如GWT更“轻量级” 有一件事一直困扰着我:虽然我的项目很小,但性能一直是一个

Javascript无处不在,在我看来,它越来越重要。大多数程序员都会同意,虽然Javascript本身很难看,但它的“领域”的确令人印象深刻。凭借HTML5的功能和现代浏览器通过Javascript部署应用程序的速度,这是一个有趣的选择:它可能是跨平台的

自然的结果是交叉编译器。主要的可能是GWT,但还有其他几种选择。我最喜欢的是Coffeescript,因为它只在Javascript上添加了一层薄薄的内容,并且比例如GWT更“轻量级”

有一件事一直困扰着我:虽然我的项目很小,但性能一直是一个重要的话题。这里有一句话

GWT SDK提供了一组核心Java API和小部件。这些允许 您需要使用Java编写AJAX应用程序,然后将源代码编译为 高度优化的JavaScript

咖啡脚本也优化了吗?因为Coffeescript似乎大量使用了非常见的Javascript功能,所以我担心它们的性能如何比较

您是否有与咖啡脚本相关的速度问题的经验?
你知道一个好的基准比较吗?

Coffescript直接编译成JavaScript,这意味着对于任何Coffescript源代码,JS中总是有一对一的等价物。这没有什么不寻常的地方。性能增益可以来自优化的因素,例如,Coffescript将数组长度存储在for循环中的一个单独变量中,而不是在每次迭代中请求它。但这在JavaScript中也应该是一种常见的做法,只是语言本身没有强制执行。

简短回答:没有

CoffeeScript生成javascript,因此其最大可能速度等于javascript的速度。但是,虽然您可以在低级别优化js代码(是的,听起来很讽刺),并获得一些性能提升,但使用CoffeeScript您无法做到这一点


但是当你选择CS而不是JS时,代码的速度不应该是你所关心的,因为对于大多数任务来说,差异是可以忽略的。

很抱歉重新提出了一个老话题,但它也与我有关。我决定执行一个小测试,我知道的最简单的性能测试之一是将连续值写入数组,随着数组的增长,内存以熟悉的方式消耗,而“for”循环在现实生活中非常常见,因此被认为是相关的

经过几番讨价还价后,我发现coffeescript最简单的方法是:

newway = -> [0..1000000]
# simpler and quicker than the example from http://coffeescript.org/#loops
# countdown = (num for num in [10..1])
这将使用闭包并返回数组作为结果。我的等价物是:

function oldway()
{
    var a = [];
    for (var i = 0; i <= 1000000; i++)
        a[i] = i;
    return a;
}
咖啡脚本速度慢了78%。我反驳说“你写的咖啡脚本的运行速度和你写的JS一样快(而且常常比JS快”)


增编:我还怀疑“JS中总是有一对一的等价物”这一流行观点。我尝试用以下代码重新创建自己的代码:

badway = ->
    a = []
    for i in [1..1000000]
        a[i] = i
    return a

尽管有相似之处,它仍然慢了7%,因为它增加了额外的方向检查(增量或减量),这意味着它不是一个直接的翻译。

这一切都很有趣,有一个事实,咖啡脚本不能比完全优化的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);
也就是说,因为coffee脚本正在生成javascript。有很多方法让它值得。遗憾的是,情况似乎并非如此

让我们举个例子:

new_way = -> [0..1000000]
new_way()
它通过coffee脚本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);
生成JS,你可能会问自己那里发生了什么???无论出于什么原因,它都在创建
i
\u 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);
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);
这个小小的改变使它比我们的咖啡脚本快。现在让我们看看生成的咖啡脚本。。。并删除那些双变量

为此:

// 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);
我想说的是,使用高级语言有很大的好处。生成的咖啡脚本未优化。但是与纯js代码没有那么远。
clockworkgeek
试图直接使用索引而不是推送的代码优化实际上似乎适得其反,并且比生成的coffeescript运行得更慢

事实是,这种优化可能很难找到和修复。另一方面,从一个版本到另一个版本,coffeescript可以为当前浏览器或解释器生成优化的js代码。CoffeeScript将保持不变,但可以再次生成以加快速度

如果您直接使用javascript编写代码,现在就有了一种方法,可以像使用真正的编译器一样对代码进行优化

另一个有趣的部分是,有一天,CoffeeScript或javascript的其他生成器可以用来分析代码(如jslint),并删除一些不需要变量的代码部分。。。使用不同的参数以不同的方式编译函数,以在不需要某些变量时加快速度。如果您有purejs,那么您将不得不期望有一个JIT编译器能够正确地完成这项工作,它对coffeescript也有好处

例如,我可以最后一次优化coffee脚本..通过删除
new\u way=(函数…
从for循环内部。一个聪明的程序员会知道,这里发生的唯一事情是在每个循环上重新影响函数,而不会改变变量。函数是在函数作用域中创建的,不会在每个循环上重新创建。也就是说,它不会改变太多

time node test.js

real    0m5.363s
user    0m0.015s
sys     0m0.000s

所以这差不多就是它。

我想对Loïc Faure Lacroix的答案补充一点

看起来,您只打印了一个浏览器的时间。顺便说一句,“x.push(i)”并不比jsperf中的“x[i]=i”快:

另一点->x.call(this)和x.apply(t
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
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);
time node test2.js

real    0m5.330s
user    0m0.000s
sys     0m0.000s
// 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
time node test.js

real    0m5.363s
user    0m0.015s
sys     0m0.000s
Chrome:  push => 79,491  ops/s; direct assignment => 3,815,588 ops/s;
IE Edge: push => 358,036 ops/s; direct assignment => 7,047,523 ops/s;
Firefox: push => 67,123  ops/s; direct assignment => 206,444   ops/s;
Chrome: 
direct call => 47,579,486 ops/s; x.call => 45,239,029 ops/s; x.apply => 15,036,387 ops/s;
IE Edge: 
direct call => 113,210,261 ops/s; x.call => 17,771,762 ops/s; x.apply => 6,550,769 ops/s;
Firefox:
direct call => 780,255,612 ops/s; x.call => 76,210,019 ops/s; x.apply => 2,559,295 ops/s;
console.time('coffee');// added manually
(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);
  };

  // manually added on both
  var i;
  for(i = 0; i != 10; i++)
  {
    new_way();
  }

}).call(this);
console.timeEnd('coffee');// added manually
console.time('js');
(function() {

  function old_way()
  {
    var i = 0, results = [];
    return (function()
    {
      for (i = 0; i <= 1000000; i++)
      {
        results[i] = i;
      }
      return results;
    })();// replaced apply
  }

  var i;
  for(i = 0; i != 10; i++)
  {
    old_way();
  }

})();// replaced call
console.timeEnd('js');
Chrome:  coffee: 305.000ms;   js: 258.000ms;
IE Edge: coffee: 5.944,281ms; js: 3.517,72ms;
Firefox: coffee: 174.23ms;    js: 159.55ms;