Все это довольно интересно, и есть одна правда: кофейный скрипт не может работать быстрее, чем полностью оптимизированный 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. Мы не хотим polute окно правильно?
(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.
Правда в том, что такого рода оптимизацию трудно найти и исправить. С другой стороны, от версии к версии, coffeescript может генерировать оптимизированный js-код для текущего браузера или интерпретаторов. CoffeeScript останется неизменным, но может быть сгенерирован снова, чтобы ускорить процесс.
Если вы пишете прямо в javascript, теперь есть способ действительно оптимизировать код так же, как и при использовании реального компилятора.
Другая интересная часть заключается в том, что однажды CoffeeScript или другие генераторы javascript могут быть использованы для анализа кода (например, jslint) и удаления частей кода, где некоторые переменные не нужны ... Компилировать функции по-разному с разными аргументами ускорить вещи, когда некоторые переменные не нужны. Если у вас есть purejs, вам следует ожидать, что есть JIT-компилятор, который будет правильно выполнять свою работу, и это хорошо для coffeescript.
Например, я мог бы оптимизировать сценарий кофе в последний раз, удалив new_way = (function...
из цикла for. Один умный программист знает, что единственное, что здесь происходит, - это повторное включение функции в каждом цикле, которая не меняет переменную. Функция создается в области видимости функции и не воссоздается в каждом цикле. Тем не менее, это не должно сильно измениться ...
time node test.js
real 0m5.363s
user 0m0.015s
sys 0m0.000s
Так что это в значительной степени так.