Chi phí của các trình xử lý ngoại lệ trong Python


97

Trong một câu hỏi khác , câu trả lời được chấp nhận đã đề xuất thay thế một câu lệnh if (rất rẻ) trong mã Python bằng một khối thử / ngoại trừ để cải thiện hiệu suất.

Đặt vấn đề về phong cách mã hóa sang một bên và giả sử rằng ngoại lệ không bao giờ được kích hoạt, thì việc có một trình xử lý ngoại lệ (hiệu suất khôn ngoan) sẽ tạo ra sự khác biệt như thế nào so với không có, so với việc có câu lệnh if-so-0?


6
Khi bạn đo lường nó, bạn đã học được gì?
S.Lott

1
Câu hỏi liên quan: stackoverflow.com/questions/1835756
tzot

Sử dụng thử / ngoại trừ nếu cơ hội kiểm soát đến ngoại trừ một phần là ít hơn và nếu / khác nếu cơ hội nhiều hơn.
shadow0359,

Câu trả lời:


112

Tại sao bạn không đo lường nó bằng cách sử dụng timeitmô-đun ? Bằng cách đó, bạn có thể xem liệu nó có liên quan đến ứng dụng của bạn hay không.

OK, vì vậy tôi vừa thử những cách sau:

import timeit

statements=["""\
try:
    b = 10/a
except ZeroDivisionError:
    pass""",
"""\
if a:
    b = 10/a""",
"b = 10/a"]

for a in (1,0):
    for s in statements:
        t = timeit.Timer(stmt=s, setup='a={}'.format(a))
        print("a = {}\n{}".format(a,s))
        print("%.2f usec/pass\n" % (1000000 * t.timeit(number=100000)/100000))

Kết quả:

a = 1
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.25 usec/pass

a = 1
if a:
    b = 10/a
0.29 usec/pass

a = 1
b = 10/a
0.22 usec/pass

a = 0
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.57 usec/pass

a = 0
if a:
    b = 10/a
0.04 usec/pass

a = 0
b = 10/a
ZeroDivisionError: int division or modulo by zero

Vì vậy, như mong đợi, việc không có bất kỳ trình xử lý ngoại lệ nào sẽ nhanh hơn một chút (nhưng sẽ thổi phồng mặt bạn khi ngoại lệ xảy ra), và try/exceptnhanh hơn một cách rõ ràng ifmiễn là điều kiện không được đáp ứng.

Nhưng tất cả đều nằm trong cùng một thứ tự độ lớn và không có vấn đề gì cả. Chỉ khi điều kiện thực sự được đáp ứng, thì ifphiên bản mới nhanh hơn đáng kể.


3
Hấp dẫn. Vì vậy, try/exceptnhanh hơnif a != 0
Thilo

10
Ahh, một sự lựa chọn tốt về từ ngữ: "tất cả đều nằm trong cùng một thứ tự độ lớn" ... Tôi nghi ngờ rằng nhiều người tránh các trường hợp ngoại lệ đã làm như vậy mong đợi họ sẽ chậm gấp 10 lần.
Garrett Bluma

Chạy mã của bạn trên Fedora của tôi với python 2.7.5 cho thấy rằng phiên bản "if" (0,08 usec / pass) nhanh hơn phiên bản "try / exception" (0,11 usec / pass) khi a = 1.
duleshi

@duleshi Thật thú vị. Tôi tự hỏi nếu nó là một thứ x86 / x64? Hoặc có lẽ các phần mở rộng bộ xử lý khác nhau?
Cơ bản

58

Câu hỏi này thực sự đã được trả lời trong Câu hỏi thường gặp về thiết kế và lịch sử :

Khối thử / ngoại trừ cực kỳ hiệu quả nếu không có ngoại lệ nào được nêu ra. Trên thực tế, bắt một ngoại lệ là tốn kém.


3
Tôi chỉ tự hỏi làm thế nào hiệu quả "cực kỳ hiệu quả" là. Rõ ràng là nó nhanh hơn ngay cả khi một câu lệnh "nếu" rất đơn giản.
Thilo

Đoạn trích bạn đã đăng là từ Câu hỏi thường gặp về thiết kế và lịch sử .
nitsas

Có lẽ "cực kỳ hiệu quả" có nghĩa là một cái gì đó giống như những gì được thực hiện trong Java ?
ebk

18

Câu hỏi này gây hiểu lầm. Nếu bạn giả sử rằng ngoại lệ không bao giờ được kích hoạt, thì không có ngoại lệ nào là mã tối ưu.

Nếu bạn giả sử rằng ngoại lệ được kích hoạt như một phần của điều kiện lỗi, bạn đã ở ngoài lĩnh vực mong muốn mã tối ưu (và có thể bạn vẫn chưa xử lý nó ở mức chi tiết như vậy).

Nếu bạn đang sử dụng ngoại lệ như một phần của quy trình kiểm soát tiêu chuẩn - đó là cách "xin tha thứ, không xin phép" của Pythonic - thì ngoại lệ sẽ được kích hoạt và chi phí phụ thuộc vào loại ngoại lệ, loại nếu và bao nhiêu phần trăm thời gian bạn ước tính ngoại lệ xảy ra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.