2013-08-27 48 views
6

Tôi đang viết hàm so sánh chuỗi thời gian không đổi (đối với node.js) và muốn tắt trình biên dịch tối ưu hóa của V8 cho hàm đơn lẻ này; việc sử dụng cờ dòng lệnh nằm ngoài câu hỏi.Cách tắt trình biên dịch tối ưu hóa của V8

Tôi biết rằng việc sử dụng khối with{} (hoặc try/catch) sẽ tắt trình biên dịch tối ưu hóa bây giờ, nhưng tôi e ngại tính năng này sẽ được sửa trong các phiên bản sau.

Có cách nào không thay đổi (và được ghi lại) vô hiệu hoá trình biên dịch tối ưu hóa của V8 không?


chức năng Ví dụ:

function constantTimeStringCompare(a, b) { 
    // By adding a `with` block here, we disable v8's optimizing compiler. 
    // Using Object.create(null) ensures we don't have any object prototype properties getting in our way.our way. 
    with (Object.create(null)){ 
     var valid = true, 
      length = Math.max(a.length, b.length); 
     while (length--) { 
      valid &= a.charCodeAt(length) === b.charCodeAt(length); 
     } 
     // returns true if valid == 1, false if valid == 0 
     return !!valid; 
    } 
} 

Và một perf test chỉ để cho vui.

+0

So sánh hằng giờ với vòng lặp 'while' trong đó ... ಠ_ಠ (có thể đó không phải là cách tiếp cận thực?) – Pointy

+0

... cũng như thế nào" hợp lệ "bao giờ là bất kỳ thứ gì khác ngoài boolean? Có lẽ tôi đang chú ý quá nhiều đến mã :) – Pointy

+0

Phần 'hằng số 'có liên quan đến độ dài của chuỗi đầu vào. Có lẽ tôi chỉ nên trả về false nếu độ dài không khớp. Tôi không thấy vấn đề với vòng lặp 'while'. –

Trả lời

8

Nếu bạn muốn cách vững chắc để làm điều đó, bạn cần phải chạy nút với --allow-natives-syntax cờ và gọi đây là:

%NeverOptimizeFunction(constantTimeStringCompare); 

Lưu ý rằng bạn nên gọi này trước khi bạn đã gọi constantTimeStringCompare, nếu chức năng đã được tối ưu hóa sau đó điều này vi phạm một khẳng định.

Nếu không with tuyên bố là đặt cược tốt nhất của bạn làm cho nó có thể tối ưu hóa sẽ là tuyệt đối trong khi hỗ trợ try/catch sẽ là hợp lý. Bạn không cần nó để ảnh hưởng đến mã của bạn mặc dù, đây sẽ là đủ:

function constantTimeStringCompare(a, b) { 
    with({}); 

    var valid = true, 
     length = Math.max(a.length, b.length); 
    while (length--) { 
     valid &= a.charCodeAt(length) === b.charCodeAt(length); 
    } 
    // returns true if valid == 1, false if valid == 0 
    return !!valid; 

} 

Chỉ nhắc đến with tuyên bố corrupts toàn bộ chứa chức năng - tối ưu hóa được thực hiện ở chức năng cấp granularity, không tính theo tuyên bố.

+0

Việc sử dụng cờ, thật không may, không phải là một tùy chọn. Tôi cảm thấy như trình biên dịch tối ưu hóa của V8 có thể tối ưu hóa khối 'with' trống rỗng, một ngày nào đó. Bạn không thấy tối ưu hóa này là một tiềm năng, nếu không, tại sao? –

+0

@DavidMurdoch Không có tối ưu hóa được thực hiện như xóa mã chết vì chức năng vô hiệu hóa tối ưu bằng cách đề cập đến 'với'. Trước khi tối ưu hóa như vậy có thể xảy ra, họ sẽ phải bắt đầu hỗ trợ 'with' trong trình biên dịch tối ưu hóa của họ, mà tôi đã nói sẽ là lunacy ngay từ đầu vì triết lý là hỗ trợ mã hợp lý. 'with' là tà ác thuần túy và thậm chí lỗi cú pháp ở chế độ nghiêm ngặt, không phải mã hợp lý mà mọi người sẽ vội vàng để tối ưu hóa. Nhưng đó là đặt cược tốt nhất của bạn nếu bạn không muốn sử dụng cờ. – Esailija

+0

'với ({});' không hoạt động ở chế độ nghiêm ngặt. – vitalets

1

Để thực sự kiểm tra chức năng được tối ưu hóa bằng phiên bản Node.js cụ thể, bạn có thể tham khảo Optimization Killers wiki của bluebird.
Tôi đã kiểm tra 3 giải pháp trên Node 7.2:

  1. with({}) - Chức năng được tối ưu hóa bằng động cơ phản lực
  2. try {} catch(e) {} - Chức năng được tối ưu hóa bằng động cơ phản lực
  3. eval(''); - Chức năng không được tối ưu hóa

Vì vậy, để đảm bảo tối ưu hóa V8 vô hiệu hóa, bạn nên thêm eval('') vào chức năng cơ thể.