2012-01-28 3 views
9

Javascript là ở khắp mọi nơi và để tâm trí của tôi liên tục đạt được tầm quan trọng. Hầu hết các lập trình viên sẽ đồng ý rằng mặc dù bản thân Javascript là xấu, nhưng "lãnh thổ" của nó chắc chắn là ấn tượng. Với khả năng của HTML5 và tốc độ của các trình duyệt hiện đại triển khai một ứng dụng thông qua Javascript là một lựa chọn thú vị: Nó có thể là nền tảng đa năng như bạn có thể nhận được.là coffeescript nhanh hơn javascript?

Kết quả tự nhiên là trình biên dịch chéo. Phần lớn có lẽ là GWT nhưng có một số tùy chọn khác ngoài đó. Yêu thích của tôi là Coffeescript vì nó chỉ thêm một lớp mỏng trên Javascript và có nhiều "nhẹ" hơn ví dụ GWT.

Chỉ có một điều đã khiến tôi lo lắng: Mặc dù dự án của tôi có hiệu suất khá nhỏ luôn là một chủ đề quan trọng. Dưới đây là một câu trích dẫn

GWT SDK cung cấp một tập hợp các API và các API Java lõi. Điều này cho phép bạn viết các ứng dụng AJAX trong Java và sau đó biên dịch mã nguồn để cao được tối ưu hóa JavaScript

là Coffeescript tối ưu hóa, quá? Kể từ khi Coffeescript dường như làm cho việc sử dụng nhiều chức năng Javascript không phổ biến, tôi lo lắng về cách so sánh hiệu suất của chúng.

Bạn có gặp phải vấn đề về tốc độ liên quan đến Coffeescript không? Bạn có biết so sánh điểm chuẩn tốt không?

+3

Chức năng không phổ biến nào mà CoffeeScript sử dụng? –

+13

"JavaScript chính nó là xấu" -> sai. – Raynos

+3

Tôi đồng ý với Raynos: mã xấu là mã không hợp lệ và có thể được viết bằng bất kỳ ngôn ngữ nào. – calvinf

Trả lời

37

Xin lỗi vì đã phục hồi một chủ đề cũ nhưng cũng liên quan đến tôi. Tôi quyết định thực hiện một bài kiểm tra nhỏ và một trong những bài kiểm tra hiệu năng đơn giản nhất mà tôi biết là viết các giá trị liên tiếp vào một mảng, bộ nhớ được tiêu thụ theo cách quen thuộc khi mảng phát triển và 'cho' các vòng lặp đủ phổ biến trong cuộc sống thực. liên quan, thích hợp.

Sau một vài cá trích đỏ tôi thấy phương pháp đơn giản nhất coffeescript là:

newway = -> [0..1000000] 
# simpler and quicker than the example from http://coffeescript.org/#loops 
# countdown = (num for num in [10..1]) 

này sử dụng một kết thúc và trả về mảng như kết quả. Tương đương của tôi là:

function oldway() 
{ 
    var a = []; 
    for (var i = 0; i <= 1000000; i++) 
     a[i] = i; 
    return a; 
} 

Như bạn có thể thấy kết quả giống nhau và nó cũng phát triển một mảng theo cách tương tự. Tiếp theo, tôi đã định hình trong crôm gấp 100 lần và trung bình.

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

Coffeescript chậm hơn 78%. Tôi bác bỏ rằng "CoffeeScript bạn viết kết thúc lên chạy càng nhanh càng tốt (và thường nhanh hơn) JS bạn sẽ có văn bản" (Jeremy Ashkenas)


Phụ Lục: Tôi cũng đã nghi ngờ về niềm tin phổ biến rằng "không luôn luôn là một trong một tương đương trong JS ". Tôi cố gắng để tái tạo mã của riêng tôi với điều này:

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

Mặc dù sự giống nhau nó vẫn tỏ ra chậm hơn 7% bởi vì nó cho biết thêm kiểm tra thêm cho hướng (tăng hoặc giảm) có nghĩa là nó không phải là một bản dịch thẳng.

+5

lý do tại sao xin lỗi vì một câu trả lời thú vị. Tôi sẽ không mong đợi sự khác biệt tuyệt vời như vậy. Chắc chắn người ta có thể lập luận rằng việc thêm tất cả các số từ 0 đến 1000000 vào một mảng không phải là một trường hợp sử dụng bình thường và bạn chỉ cần nhìn vào một trình duyệt. Nhưng 78%! Đó là khó khăn +1 – lhk

+0

điều này sẽ là câu trả lời vì tác giả mất thời gian để đo lường và chỉ ra vấn đề trong js được tạo ra từ cà phê. Lý do duy nhất để sử dụng cà phê là tất cả về năng suất. – nXqd

+0

Các đóng cửa thường được báo cáo là thoát hiệu suất trong Javascript. Coffeescript sử dụng chúng rộng rãi, ngay cả khi họ sẽ không hoàn toàn cần thiết. – relet

8

Bản ghi trực tiếp biên dịch trực tiếp thành JavaScript, có nghĩa là luôn có một từ một đến một tương đương trong JS cho bất kỳ nguồn Coffeescript nào. Không có gì không phổ biến về nó. Mức tăng hiệu suất có thể đến từ những thứ được tối ưu hóa, ví dụ: thực tế là Coffescript lưu trữ chiều dài mảng trong một biến riêng biệt trong vòng lặp for thay vì yêu cầu nó trong mỗi lần lặp. Nhưng đó cũng là một thực tế phổ biến trong JavaScript, nó chỉ không được thực thi bởi chính ngôn ngữ đó.

+1

Câu trả lời hay. Tôi đoán có thể có một lợi ích tuyệt vời nếu JS CoffeeScript tạo ra thông minh hơn những gì nhà phát triển khác có ... mà tôi đoán là không phổ biến –

+0

Tạo một ngôn ngữ mới kết hợp các thực hành tốt nhất là một ý tưởng hay. Vấn đề tôi thấy là khi nó cố gắng quá lạ mắt. Và tất cả mọi người đều biết lý do tại sao CoffeeScript tạo ra JS. – Daff

+0

@AdamRackis CoffeeScript trung bình tạo ra JavaScript tồi tệ hơn, sau đó các nhà phát triển trung bình có thể viết. Bạn có thể nhận được may mắn và tìm thấy CS tạo ra JavaScript tốt hơn cho các nhà phát triển shit nhưng nếu bạn có shit phát triển bạn có vấn đề lớn hơn. – Raynos

11

Câu trả lời ngắn: Không.

CoffeeScript tạo javascript, do đó tốc độ tối đa có thể tương đương với tốc độ của javascript. Nhưng trong khi bạn có thể tối ưu hóa mã js tại mức thấp (vâng, nghe có vẻ mỉa mai) và tăng hiệu suất - với CoffeeScript bạn không thể làm điều đó.

Nhưng tốc độ mã không phải là mối quan tâm của bạn, khi chọn CS trên JS, vì sự khác biệt là không đáng kể đối với hầu hết các tác vụ.

21

Điều này hoàn toàn tương tác và có một sự thật, tập lệnh cà phê không thể hoạt động nhanh hơn javascript được tối ưu hóa hoàn toàn.

Điều đó nói rằng, vì tập lệnh cà phê đang tạo javascript. Có nhiều cách để làm cho nó đáng giá. Đáng buồn thay, nó không có vẻ là trường hợp được nêu ra.

Hãy lấy ví dụ:

new_way = -> [0..1000000] 
new_way() 

Nó biên dịch này với kịch bản cà phê 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); 

Và mã được cung cấp bởi clockworkgeek là

function oldway() 
{ 
    var a = []; 
    for (var i = 0; i <= 1000000; i++) 
     a[i] = i; 
    return a; 
} 
oldway() 

Nhưng kể từ khi kịch bản cà phê ẩn các chức năng bên trong một phạm vi, chúng ta nên làm điều đó cho javascript quá. Chúng tôi không muốn làm cong cửa sổ phải không?

(function() { 
    function oldway() 
    { 
     var a = []; 
     for (var i = 0; i <= 1000000; i++) 
      a[i] = i; 
     return a; 
    } 
    oldway() 
}).call(this); 

Vì vậy, ở đây chúng tôi có mã thực hiện điều tương tự. Và sau đó chúng tôi muốn thực sự thử nghiệm cả hai phiên bản một vài lần.

kịch bản Coffee

for i in [0..100] 
    new_way = -> [0..1000000] 
    new_way() 

tạo JS, và bạn có thể tự hỏi mình những gì đang diễn ra ở đó ??? Nó tạo ra i_i vì bất kỳ lý do gì. Rõ ràng với tôi từ hai điều này, chỉ có một là cần thiết.

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

Bây giờ chúng ta sẽ cập nhật Javascript của mình.

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

Vì vậy, các kết quả:

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 

Các js mất

time node test2.js 

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

Vì vậy, bạn có thể tự hỏi mình ... những gì cà phê kịch bản địa ngục là nhanh hơn ??? và sau đó bạn nhìn vào mã và tự hỏi mình ... vì vậy hãy cố gắng khắc phục điều đó!

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

Sau đó chúng tôi sẽ làm một sửa chữa nhỏ để kịch bản JS và thay đổi a[i] = i-a.push(i) Và sau đó cho phép thử lại ... và sau đó BOOM

time node test2.js 

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

thay đổi nhỏ này đã làm cho nó nhanh hơn so với chúng tôi CoffeeScript Bây giờ cho phép nhìn vào CoffeeScript tạo ... và loại bỏ các biến đôi ...

này:

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

và BOOM

time node test.js 

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

Vâng những gì tôi đang cố gắng để nói là có những lợi ích tuyệt vời để sử dụng một ngôn ngữ cao hơn. CoffeeScript được tạo không được tối ưu hóa. Nhưng không xa mã js thuần túy. Mã tối ưu hóa mà clockworkgeek đã cố gắng sử dụng với việc sử dụng chỉ mục trực tiếp thay vì đẩy thực sự dường như ngược lại và làm việc chậm hơn so với coffeescript được tạo ra.

Sự thật rằng loại tối ưu hóa như vậy có thể khó tìm và sửa chữa. Mặt khác, từ phiên bản này sang phiên bản khác, coffeescript có thể tạo mã js được tối ưu hóa cho trình duyệt hoặc trình thông dịch hiện tại. CoffeeScript sẽ không thay đổi nhưng có thể được tạo lại để tăng tốc mọi thứ.

Nếu bạn viết trực tiếp bằng javascript, bây giờ có cách để thực sự tối ưu hóa mã càng nhiều càng tốt với một trình biên dịch thực.

Một phần thú vị khác là một ngày, CoffeeScript hoặc các trình tạo khác có thể được sử dụng để phân tích mã (như jslint) và loại bỏ các phần của mã mà một số biến không cần thiết ... các đối số để tăng tốc độ khi không cần một số biến. Nếu bạn có purejs, bạn sẽ phải mong đợi rằng có một trình biên dịch JIT sẽ làm công việc đúng và tốt cho coffeescript.

Ví dụ: tôi có thể tối ưu hóa tập lệnh cà phê lần cuối .. khi xóa new_way = (function... từ bên trong vòng lặp for. Một lập trình viên thông minh sẽ biết rằng điều duy nhất xảy ra ở đây là tái tạo chức năng trên mỗi vòng lặp mà không thay đổi biến. Hàm được tạo trong phạm vi hàm và không được tạo lại trên mỗi vòng lặp. Điều đó nói rằng nó không nên thay đổi nhiều ...

time node test.js 

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

Vì vậy, điều này là khá nhiều.

+0

Bạn đã thực hiện thay đổi nào đối với mã CoffeeScript đã tạo ra khối cuối cùng? – pilau

+0

Tôi đã xóa '_i'. Tôi đã không thay đổi mã coffescript. Tôi đã chỉnh sửa mã được tạo. –

+0

Được rồi. Lúc đầu, tôi nghĩ bạn đã trình bày một giải pháp thiết thực để làm cho CoffeeScript xuất ra mã tốt hơn. Bây giờ tôi thấy rằng bạn đã thay đổi điều đó, chỉ để làm cho quan điểm của bạn rằng trình biên dịch CoffeeScript là một lớp có thể được cải tiến về mặt kỹ thuật để mang lại nhiều mã được tối ưu hóa hơn. – pilau

1

Tôi muốn thêm một cái gì đó để câu trả lời của Loïc Faure-Lacroix ...

Dường như, rằng bạn chỉ in thời gian của một Browser. Và btw "x.push (i)" không nhanh hơn là "x [i] = i" theo jsperf: 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; 

Một điểm -> x.call (this) và x.apply (điều này) ... Tôi không thấy lý do nào về hiệu suất đó. Ngay cả jsperf cũng xác nhận rằng: 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; 

Trước tiên, tôi đã sử dụng Trình duyệt thực tế.

Thứ hai - Tôi mở rộng thử nghiệm bằng vòng lặp for, bởi vì với một cuộc gọi, kiểm tra là ngắn ...

Cuối cùng nhưng không kém phần quan - bây giờ các cuộc thử nghiệm cho tất cả các trình duyệt là như sau:


Ở đây tôi sử dụng CoffeeScript 1.10.0 (biên soạn với cùng mã đưa ra trong câu trả lời của ông)

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 

Bây giờ 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'); 

giá trị giới hạn của vòng lặp for là thấp, bởi vì bất kỳ cao nó sẽ là một thử nghiệm khá chậm (10 * 1000000 cuộc gọi) ...

Kết quả

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

Ở đây tôi phải có đề cập đến, đó không phải lúc nào cũng cà phê là chậm nhất trong thử nghiệm này. Bạn có thể thấy điều đó bằng cách kiểm tra các mã đó trong firefox.

câu trả lời cuối cùng của tôi:

Đầu tiên phải nói - Tôi không thực sự quen thuộc với coffeescript, nhưng tôi nhìn vào nó, bởi vì tôi đang sử dụng Atom Editor và muốn cố gắng xây dựng gói đầu tiên của tôi ở đó, nhưng drived quay lại Javascript ... Vì vậy, nếu có bất cứ điều gì sai, bạn có thể sửa tôi.

Với coffeescript bạn có thể viết ít mã hơn, nhưng nếu nói đến tối ưu hóa, mã sẽ bị nặng. Ý kiến ​​của riêng tôi -> Tôi không thấy bất kỳ cái gọi là "năng suất" trong ngôn ngữ Coffeescripting này ...

Để quay lại màn trình diễn :: Trình duyệt được sử dụng nhiều nhất là Trình duyệt Chrome (src: w3schools.com/ trình duyệt/browser_stats.asp) với 60% và các thử nghiệm của tôi cũng cho thấy Javascript được nhập theo cách thủ công chạy nhanh hơn một chút so với Coffeescript (ngoại trừ IE ... - nhanh hơn nhiều). Tôi muốn giới thiệu Coffeescript cho các dự án nhỏ hơn, nhưng nếu không có ai, hãy giữ ngôn ngữ bạn thích.