2010-03-26 29 views
25

Tôi thường không phải là một fan hâm mộ của microbenchmarks. Nhưng điều này có một kết quả rất thú vị. http://ernestdelgado.com/archive/benchmark-on-the-floor/Tại sao Math.floor của Javascript là cách chậm nhất để tính toán sàn trong Javascript?

Nó gợi ý rằng Math.floor là cách chậm nhất để tính toán sàn bằng Javascript. ~~n, n|n, n&n tất cả đều nhanh hơn.
Điều này có vẻ khá gây sốc như tôi mong đợi rằng mọi người triển khai Javascript trong các trình duyệt hiện đại ngày nay sẽ là một số người khá thông minh.

Sàn có làm điều gì đó quan trọng mà các phương pháp khác không làm được không? Có lý do gì để sử dụng nó không?

+3

'~~ n',' n | n' và 'n & n' không tạo ra kết quả tương tự như' Math.floor'. Ba đầu tiên chỉ có thể trả về số nguyên 32 bit. Hãy thử 'n = 50000000000.4'. – kennytm

+0

Trong trình duyệt của tôi (FF 3.6.something), chúng đều có cùng tốc độ trong kết quả (khoảng "3", bất kể điều đó có nghĩa là gì). Hãy thử nó trên các trình duyệt khác nhau (các thử nghiệm nhỏ được cung cấp ở phía dưới) thay vì chỉ lấy kết quả theo mệnh giá. Có thực sự là không có lý do tại sao nó nên được chú ý chậm hơn. –

+3

Trên thực tế, chạy điểm chuẩn của mình trong FF 3.6 cho thấy 'Math.floor' là nhanh nhất –

Trả lời

26

Nó không liên quan gì đến trình duyệt hiện đại. Nó phải làm với việc thực hiện tiêu chuẩn ECMA. Bạn không thể chỉ thay đổi cách một chức năng nhất định thực hiện ngay cả khi có một cách nhanh hơn. Nó có thể phá vỡ mã hiện có.

Math.Floor phải tính đến rất nhiều trường hợp xử lý các loại khác nhau. Có thể họ đã thực hiện các kịch bản khác nhau nhanh hơn bằng cách thực hiện các đoạn cắt ngắn như bạn mô tả? Có lẽ họ có thể, nhưng điều đó có thể đã phá vỡ các kịch bản khác. Chỉ vì một cái gì đó trên bề mặt trông nhỏ, không có nghĩa là không có một tảng băng trôi bên dưới.

+7

+1 Chậm hay không, đó có lẽ là điều duy nhất làm nó * chính xác * –

+1

Điểm tốt. 'Math.floor (" foo ")' trả về 'NaN'. Nhưng nếu đó là lợi ích duy nhất tôi bị cám dỗ sử dụng phương pháp khác. Ít nhất cho đến khi Javascript hỗ trợ phân chia số nguyên. – z5h

+0

Tôi không nói rằng bạn nên luôn luôn sử dụng Math.Floor, nó là chậm. Chỉ khi họ thiết kế một chức năng họ phải tính đến rất nhiều kịch bản khác nhau mà mọi người có thể làm. Một điều về JS là nó có nghĩa là để dễ dàng để chương trình với điều đó có nghĩa là họ đã có biện pháp phòng ngừa thêm khi xây dựng nó và trong một số kịch bản làm cho họ mất một chặng đường dài xung quanh. – kemiller2002

31

Lý do chính Math.floor là chậm hơn (nơi thực sự là - trong một số thử nghiệm tôi đã thực hiện nó nhanh hơn) là nó liên quan đến một cuộc gọi chức năng. Các triển khai JavaScript cũ hơn không thể thực hiện các cuộc gọi hàm nội tuyến. Các công cụ mới hơn có thể nội tuyến cuộc gọi, hoặc ít nhất là tra cứu tài sản nhanh hơn, nhưng chúng vẫn cần một điều kiện bảo vệ trong trường hợp bạn (hoặc một số tập lệnh khác) ghi đè hàm Math.floor. Tuy nhiên, chi phí rất thấp, vì vậy không có nhiều khác biệt về tốc độ.

Quan trọng hơn mặc dù, như đã được đề cập trong một số ý kiến, các phương pháp khác không tương đương. Tất cả đều hoạt động bằng cách thực hiện các thao tác bitwise. Các toán tử bitwise tự động chuyển đổi các toán hạng của chúng thành các số nguyên 32 bit bằng cách cắt bớt số. Đó là tốt nếu số lượng phù hợp trong 32 bit, nhưng số JavaScript là 64-bit nổi, có thể lớn hơn nhiều so với 2147483647.

Chúng cũng cho kết quả khác nhau cho số âm, kể từ khi chuyển sang số nguyên cắt và Math.floor luôn luôn tròn xuống. Ví dụ: Math.floor(-2.1) === -3, nhưng (-2.1) | (-2.1) === -2.

Nếu bạn biết bạn chỉ xử lý các số dương nhỏ hơn 2147483648 và bạn cần phải nén từng chút hiệu suất ra khỏi mã của mình trong các trình duyệt cũ hơn (Hãy chắc chắn đây thực sự là nút cổ chai đầu tiên. .), Tôi sẽ sử dụng một phương pháp đơn giản hơn: x|0. Nó không đánh giá biến hai lần, và nó hoạt động ngay cả khi x là một biểu thức (chỉ cần chắc chắn để đặt nó trong dấu ngoặc đơn, do đó bạn không chạy vào các vấn đề ưu tiên).

+0

"JavaScript không thể thực hiện các hàm nội tuyến vì nó là động và bạn có thể thay thế Math.floor bằng một hàm khác." Đó không phải là một chuỗi. Trình biên dịch JIT có thể và thực hiện các cuộc gọi hàm nội tuyến động. Truy tìm JIT là đặc biệt tốt ở đây. Tính năng động được xử lý bằng kiểm tra bảo vệ hoặc thêm trình kích hoạt không hợp lệ. Triển khai cụ thể có thể hoặc không thể nội tuyến. Vì vậy, cũng như với tất cả các tối ưu hóa vi mô, nếu nó thực sự quan trọng, hãy đo lường nó trên các nền tảng mục tiêu của bạn. –

+0

@Ants: Điểm tốt. Đó là những gì tôi đã nhận được với các giá trị chức năng được lưu trong bộ nhớ cache, nhưng tôi đã nói nó không chính xác. –

+6

Tôi biết câu trả lời này là một vài năm tuổi, nhưng V8 inlines chức năng cuộc gọi bây giờ, và điều này dẫn đến ['Math.floor' thực hiện cũng như hack bitwise] (http://jsperf.com/js-floors). – josh3736

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