Mu.
Nghiêm túc bây giờ, điều đó không quan trọng. Không cho các ví dụ kích thước này. Cả hai đều có cùng một phức tạp. Nếu mã của bạn không đủ nhanh cho bạn, đây có lẽ là một trong những địa điểm cuối cùng bạn xem.
Bây giờ, nếu bạn thực sự muốn biết cái nào nhanh hơn, hãy đo chúng. Trên SBCL, bạn có thể gọi từng hàm trong một vòng lặp và đo thời gian. Vì bạn có hai hàm đơn giản, time
là đủ. Nếu chương trình của bạn phức tạp hơn, thì profiler sẽ hữu ích hơn. Gợi ý: nếu bạn không cần một profiler cho phép đo của bạn, bạn có thể không cần phải lo lắng về hiệu suất.
Trên máy tính của tôi (SBCL 64 bit), tôi chạy chức năng của bạn và nhận điều này:
CL-USER> (time (loop repeat 1000 do (factorial_recursion 1000)))
Evaluation took:
0.540 seconds of real time
0.536034 seconds of total run time (0.496031 user, 0.040003 system)
[ Run times consist of 0.096 seconds GC time, and 0.441 seconds non-GC time. ]
99.26% CPU
1,006,632,438 processor cycles
511,315,904 bytes consed
NIL
CL-USER> (time (loop repeat 1000 do (factorial_loop 1000)))
Evaluation took:
0.485 seconds of real time
0.488030 seconds of total run time (0.488030 user, 0.000000 system)
[ Run times consist of 0.072 seconds GC time, and 0.417 seconds non-GC time. ]
100.62% CPU
902,043,247 processor cycles
511,322,400 bytes consed
NIL
Sau khi đưa chức năng của bạn trong một tập tin với (declaim (optimize speed))
ở phía trên, lần đệ quy giảm xuống còn 504 mili giây và thời gian vòng lặp giảm xuống còn 475 mili giây.
Và nếu bạn thực sự muốn biết điều gì đang xảy ra, hãy thử dissasemble
về chức năng của bạn và xem những gì trong đó.
Một lần nữa, điều này có vẻ không phải vấn đề với tôi. Cá nhân, tôi cố gắng sử dụng Common Lisp như một ngôn ngữ kịch bản để tạo mẫu, sau đó lược tả và tối ưu hóa các phần chậm. Bắt từ 500ms đến 475ms là không có gì. Ví dụ, trong một số mã cá nhân, tôi nhận được một vài đơn đặt hàng tăng tốc độ lớn bằng cách thêm một loại phần tử vào một mảng (do đó làm cho mảng lưu trữ 64 lần nhỏ hơn trong trường hợp của tôi). Chắc chắn, về lý thuyết nó sẽ nhanh hơn để tái sử dụng mảng đó (sau khi làm cho nó nhỏ hơn) và không phân bổ nó hơn và hơn. Nhưng chỉ cần thêm :element-type bit
vào đó là đủ cho tình huống của tôi - nhiều thay đổi hơn sẽ đòi hỏi nhiều thời gian hơn cho rất ít lợi ích bổ sung. Có lẽ tôi cẩu thả, nhưng 'nhanh' và 'chậm' không có ý nghĩa gì với tôi. Tôi thích 'đủ nhanh' và 'quá chậm'. Cả hai chức năng của bạn là 'đủ nhanh' trong hầu hết các trường hợp (hoặc cả hai đều 'quá chậm' trong một số trường hợp) nên không có sự khác biệt thực sự giữa chúng.
Nếu hàm của bạn có tính đệ quy đuôi, về cơ bản nó giống hệt với vòng lặp. Việc đệ quy đuôi có thể được tối ưu hóa thành một vòng lặp đơn giản, làm cho chúng giống hệt nhau. Chức năng của bạn không phải là đệ quy đuôi, mặc dù. – Gabe
thay thế decf bằng 1-. –
@Gabe, Trong khi đuôi đệ quy có thể được tối ưu hóa cho một vòng lặp nó là đáng chú ý rằng Common Lisp triển khai không cần thiết để tối ưu hóa các cuộc gọi đuôi, mặc dù nhiều triển khai làm. –