2012-04-02 35 views
8

http://jsperf.com/testing-foreach-vs-for-looparray.forEach chạy nhanh hơn lặp gốc? Làm sao?

Tôi hiểu rằng Test Case 2 sẽ chạy chậm hơn Test Case 1 - Tôi muốn xem chậm hơn bao nhiêu. Hãy tưởng tượng sự ngạc nhiên của tôi khi tôi thấy nó chạy nhanh hơn!

Điều gì đang xảy ra ở đây? Behind the scene optimizaiton? Hoặc là .forEach sạch hơn và nhanh hơn?

Testing trong Chrome 18.0.1025.142 32-bit trên Windows Server 2008 R2/7 64-bit

+1

'forEach' có thể có một số tối ưu hóa gốc hoặc cái gì đó. –

+3

Hơn nữa, bạn thậm chí không nhận được giá trị từ mảng trong Test Case 1, bạn đang ghi nhật ký thay vì 'mảng [i]' –

+0

1), bạn không nên tạo mảng trên mọi thử nghiệm, bạn có thể xác định vars có thể truy cập được trên tất cả các thử nghiệm 2) bạn đang kiểm tra '.length' mỗi vòng – ajax333221

Trả lời

7

Có nhiều tối ưu hóa lặp rằng for vòng lặp của bạn là mất tích như:

  • bộ nhớ cache mảng chiều dài
  • lặp ngược
  • sử dụng ++ truy cập thay vì truy cập ++

Đây là những cái mà tôi đã nghe nói và sử dụng, tôi chắc chắn có nhiều hơn. Nếu bộ nhớ phục vụ cho tôi đúng, vòng lặp lặp lại trong khi vòng lặp là nhanh nhất trong tất cả các cấu trúc lặp (trong hầu hết các trình duyệt).

Xem this jsperf để biết một số ví dụ.

Chỉnh sửa: liên kết cho postfix vs prefix perf testiterating backwards. Tôi không thể tìm thấy tham chiếu của mình cho việc sử dụng + = 1 thay vì ++, vì vậy tôi đã xóa nó khỏi danh sách.

+0

Tôi đã nghe nói rằng với C++ tôi nhanh hơn i ++, không biết liệu điều đó cũng áp dụng cho Javascript –

+0

lặp lại và sử dụng '+ = 1' thay vì' ++ 'thực sự không thay đổi gì trong JS. – kirilloid

+0

@kirilloid + = và ++ là hai toán tử hoàn toàn khác nhau có thể chạy ở các tốc độ khác nhau trong các triển khai phân tích cú pháp khác nhau và giảm dần so với gia tăng là một tối ưu hóa vi mô nổi tiếng. tôi sẽ chỉnh sửa để thêm tài liệu tham khảo. – jbabey

0

Chúng tương tự như vậy đối với tôi trong Opera. Một cái gì đó cần lưu ý là điều kiện của bạn trong for() là array.length. Nếu bạn nhớ cache độ dài của mảng trong một biến, và sau đó lặp lại, bạn sẽ thấy hiệu suất tốt hơn.

1

Đọc length từ array ở mỗi lần lặp lại có thể chậm, nhưng forEach chậm hơn, khiến cho cuộc gọi chức năng không hoạt động kém trong js.

PS: forEach chậm hơn 14% so với FF10.

+0

Tôi nghĩ rằng nó vẫn còn quan trọng nhưng tôi tin rằng các JIT đã thực hiện các cuộc gọi chức năng đáng kể zippier. –

+0

Me too =) Đặc biệt sau đó, tôi tăng tốc mã JS CPU nặng ~ 5 lần chỉ với các chức năng nội tuyến. – kirilloid

+0

Không có vấn đề gì tôi cố gắng, forEach luôn nhanh hơn trong Chrome. – trusktr

0

Có thể for() chậm hơn vì vòng lặp áp dụng 'array.length' cho mỗi lần lặp, để có độ dài của mảng.

Hãy thử:

var nri = array.length; 
for(var i = 0; i < nri; i++){ 
    // ... 
} 
3

UPDATE:

Rất nhiều các thủ thuật cũ trong các câu trả lời là tuyệt vời cho giải thích JS trong trình duyệt cũ.

Trong mọi triển khai JS hiện đại bao gồm tất cả các trình duyệt hiện đại, Node và các bản xem trước trên thiết bị di động mới nhất, các chức năng nội tuyến có thể được JIT (trình biên dịch JS) lưu vào bộ nhớ cache. Nó được sử dụng để được đối diện, nơi chỉ cần thực hiện cuộc gọi đến một chức năng nhiều lần yêu cầu một quá trình xây dựng/teardown có thể làm giảm nghiêm trọng hiệu suất của một vòng lặp không tầm thường.

Để có hiệu suất tốt nhất, tôi muốn tránh tham chiếu bất kỳ thứ gì không được chuyển làm đối số hoặc được xác định bên trong chính hàm nếu bạn không phải làm như vậy. Tôi không chắc chắn 100% rằng vấn đề nhưng tôi có thể thấy lý do tại sao nó có thể.

Giá trị tốt hơn liên quan đến bất kỳ loại quy trình tra cứu nào như độ dài mảng hoặc thuộc tính nút DOM có lẽ cũng được lưu vào bộ nhớ cache tốt nhất.

Nhưng ngoài ra tôi muốn cố gắng chỉ để nguyên tắc cơ bản về tránh việc làm hướng dẫn những nỗ lực tuyệt vời của bạn. Việc tính toán trước những thứ không cần phải tính toán lại trong một vòng lặp, hoặc việc lưu vào bộ nhớ đệm một kết quả của bộ chọn truy vấn là var thay vì lục lọi trong DOM nhiều lần là những ví dụ hay về điều này. Cố gắng hết sức để tận dụng lợi thế của hành vi JIT có lẽ sẽ trở nên khá phức tạp và không có khả năng nắm giữ theo thời gian hoặc trên tất cả các JIT.

OLD ĐÁP:

Ok, quên tường văn bản. điểm Bullet:

var i = someArray.length; //length is cached 
someArray.reverse(); //include this only if iterating in 0-(length-1) order is important 

while(i--){ 
//run a test statement on someArray[i]; 
} 
  • chiều dài bộ nhớ đệm và ngay lập tức được chuyển thể thành các chỉ số

  • Lợi ích của việc lặp lại ngược trong JS AFAIK là tránh một toán tử logic với hai toán hạng. Trong trường hợp này, chúng tôi chỉ đang đánh giá một số. Đó là sự thật hoặc nó là số không và sai.

  • Tôi cũng thấy nó thanh lịch.

Các vấn đề liên quan