簡體   English   中英

coffeescript比javascript更快?

[英]is coffeescript faster than javascript?

Javascript無處不在,在我看來,它一直在變得越來越重要。 大多數程序員都同意,雖然Javascript本身很難看,但它的“領域”確實令人印象深刻。 憑借HTML5的功能和現代瀏覽器的速度,通過Javascript部署應用程序是一個有趣的選擇:它可能是你可以獲得的跨平台。

自然的結果是交叉編譯器。 主要可能是GWT,但還有其他幾種選擇。 我最喜歡的是Coffeescript,因為它只在Javascript上添加了一個薄層,並且比例如GWT更“輕量級”。

只有一件事一直困擾着我:雖然我的項目相當小,但性能始終是一個重要的話題。 這是一個引用

GWT SDK提供了一組核心Java API和小部件。 這些允許您用Java編寫AJAX應用程序,然后將源代碼編譯為高度優化的JavaScript

Coffeescript也被優化了嗎? 由於Coffeescript似乎大量使用非常見的Javascript功能,我擔心他們的性能如何比較。

您是否有過與Coffeescript相關的速度問題的經歷? 你知道一個很好的基准比較嗎?

抱怨復活一個古老的話題,但它也讓我很擔心。 我決定執行一個小測試,我知道的一個最簡單的性能測試是將連續值寫入數組,隨着數組的增長,內存以熟悉的方式消耗,並且'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;
}

正如您所看到的,結果是相同的,它也以類似的方式生成數組。 接下來,我用chrome分析了每次100次的平均值。

newway() | 78.5ms
oldway() | 49.9ms

Coffeescript慢了78%。 我反駁說“你寫的CoffeeScript最終運行的速度和你寫的JS一樣快(並且通常比它快)”( Jeremy Ashkenas


附錄:我還懷疑人們普遍認為“JS中始終存在一對一的等同物”。 我嘗試用這個重新創建自己的代碼:

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

盡管有相似之處,它仍然被證明慢了7%,因為它增加了對方向(增量或減量)的額外檢查,這意味着它不是直接平移。

這一切都非常有趣,並且有一個道理,咖啡腳本不能比完全優化的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 Now更快,讓我們看一下生成的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);

和BOOM

time node test.js

real    0m5.373s
user    0m0.000s
sys     0m0.000s

那么我想說的是使用更高級的語言有很大的好處。 生成的CoffeeScript未進行優化。 但與純粹的js代碼相差不遠。 clockworkgeek嘗試使用直接使用索引而不是推送的代碼優化實際上似乎適得其反,並且比生成的coffeescript工作得慢。

事實上,這種優化很難找到並修復。 另一方面,從版本到版本,coffeescript可以為當前的瀏覽器或解釋器生成優化的js代碼。 CoffeeScript將保持不變,但可以再次生成以加快速度。

如果你直接用javascript編寫,現在有辦法真正優化代碼,就像使用真正的編譯器一樣。

另一個有趣的部分是,有一天,CoffeeScript或javascript的其他生成器可用於分析代碼(如jslint)並刪除不需要某些變量的代碼部分...使用不同的參數編譯函數以加快速度不需要某些變量的事情。 如果你有purejs,你將不得不期望有一個JIT編譯器能夠正確地完成工作並且它對coffeescript也有好處。

例如,我可以最后一次優化咖啡腳本..通過從for循環內部移除new_way = (function... 。一個聰明的程序員會知道這里發生的唯一事情是對每個循環的函數的影響不會改變變量。函數在函數范圍內創建,不會在每個循環中重新創建。也就是說它不應該改變太多......

time node test.js

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

所以這就是它。

簡答:

CoffeeScript生成javascript,因此其最大可能速度等於javascript的速度。 但是雖然你可以在低級別優化js代碼(是的,聽起來很諷刺)並獲得一些性能提升 - 使用CoffeeScript你不能這樣做。

但是在選擇CS over JS時,代碼的速度不應該是您的關注,因為大多數任務的差異可以忽略不計。

Coffescript直接編譯為JavaScript,這意味着在JS中對於任何Coffeescript源始終存在一對一的等價物。 關於它沒有什么不相同之處。 性能增益可以來自優化的事物,例如Coffescript將Array長度存儲在for循環中的單獨變量中而不是在每次迭代中請求它。 但這也應該是JavaScript中的常見做法,它本身並不是由語言本身強制執行的。

我想在LoïcFaure-Lacroix的答案中添加一些內容......

看來,你只打印了一個瀏覽器的時間。 根據jsperf,btw“x.push(i)”並不快“x [i] = i”: https ://jsperf.com/array-direct-assignment-vs-push/130

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;

另一點 - > x.call(this)和x.apply(this)......我沒有看到任何性能原因。 甚至jsperf也證實了這一點: http ://jsperf.com/call-apply-segu/18

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;

首先提一下 - 我使用了實際的瀏覽器。

其次 - 我通過for循環擴展了測試,因為只需一次調用,測試就是縮短...

最后但並非最不重要 - 現在所有瀏覽器的測試如下:


在這里,我使用了CoffeeScript 1.10.0(使用他的答案中給出的相同代碼編譯)

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

現在是Javascript

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');

for循環的限制值很低,因為任何更高的測試都是非常緩慢的(10 * 1000000調用)......

結果

Chrome:  coffee: 305.000ms;   js: 258.000ms;
IE Edge: coffee: 5.944,281ms; js: 3.517,72ms;
Firefox: coffee: 174.23ms;    js: 159.55ms;

在這里我必須要提到的是,並不總是咖啡是這次測試中最慢的。 您可以通過在Firefox中測試這些代碼來看到它。

我的最終答案是:

首先要說的是 - 我對coffeescript並不是很熟悉,但是我調查了一下,因為我正在使用Atom編輯器,並想嘗試在那里構建我的第一個包,但是又回到了Javascript ......所以如果有什么不對的話你可以糾正我。

使用coffeescript,您可以編寫更少的代碼,但如果涉及優化,則代碼會變得很重。 我自己的觀點 - >我沒有在這種Coffeescripting語言中看到任何所謂的“生產力”......

回到表演::最常用的瀏覽器是Chrome瀏覽器(src:w3schools.com/browsers/browsers_stats.asp)60%,我的測試也顯示手動輸入的Javascript運行速度比Coffeescript快一點(除了IE ...... - 快得多。 我會推薦Coffeescript用於較小的項目,但如果沒有人介意的話,請保持你喜歡的語言。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM