2015-07-13 15 views
5

Lấy cảm hứng từ câu trả lời cho this SO question tôi lấy mã để kiểm tra một vòng lặp bắt buộc chống lại đệ quy đuôi:mã byte chậm với đuôi đệ quy

let rec nothingfunc i = 
    match i with 
    | 1000000000 -> 1 
    | _ -> nothingfunc (i+1) 

let nothingloop1() = 
    let i = ref 0 in 
    while !i < 1000000000 do incr i done; 
    1 

let timeit f v = 
    let t1 = Unix.gettimeofday() in 
    let _ = f v in 
    let t2 = Unix.gettimeofday() in 
    t2 -. t1 

let() = 
    Printf.printf "recursive function: %g s\n%!" (timeit nothingfunc 0); 
    Printf.printf "while loop with ref counter buitin incr: %g s\n%!" (timeit nothingloop1()); 

Đối với bytecode và mã gốc kết quả là

[email protected]:~> ./bench_loop 
recursive function: 20.7656 s 
while loop with ref counter buitin incr: 12.0642 s 
[email protected]:~> ./bench_loop.opt 
recursive function: 0.755594 s 
while loop with ref counter buitin incr: 0.753947 s 

Câu hỏi đặt ra là: lý do cho sự khác biệt lớn từ 20 đến 12 giây thời gian thực hiện là gì?

Chỉnh sửa, kết luận của tôi:

Một cuộc gọi chức năng apply (trong mã byte) liên quan đến việc kiểm tra ngăn xếp kích thước, chồng mở rộng càng tốt, và một tấm séc cho tín hiệu. Để có hiệu suất tối đa, trình biên dịch mã gốc sẽ phân phối.

(Side lưu ý:. Hỏi ở đây trên SO vì nó là công cụ tìm kiếm thân thiện)

+1

chọn tham gia ocamlopt là viết tắt của tối ưu hóa. Trình biên dịch Bytecode thực hiện tối ưu hóa ít hơn, vì nó không bao giờ là mục đích của nó. Mặc dù nhiều tối ưu hóa vẫn được thực hiện. Và, ví dụ, trên phiên bản hiện tại của trình biên dịch (4.03) sự khác biệt là khoảng 10% (9.3 vs 8.3 giây). – ivg

Trả lời

4

xem kết quả của ocamlfind ocamlc -package unix test.ml -dlambda

(nothingloop1/1010 = 
    (function param/1022 
     (let (i/1011 =v 0) 
     (seq (while (< i/1011 100000000) (assign i/1011 (1+ i/1011))) 1))) 

(nothingfunc/1008 
    (function i/1009 
    (if (!= i/1009 100000000) (apply nothingfunc/1008 (+ i/1009 1)) 1))) 

Vì vậy, rõ ràng assign nhanh hơn apply. Dường như có các kiểm tra cho các luồng tràn và các tín hiệu tại các lời gọi hàm, nhưng không phải là một phép gán đơn giản. Để biết chi tiết, bạn phải xem xét: https://github.com/ocaml/ocaml/blob/trunk/byterun/interp.c

+0

OK, đã tìm thấy nó. Điều này trông giống như một thông dịch viên Forth. –

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