ค่าใช้จ่ายของตัวจัดการข้อยกเว้นใน Python


99

ในคำถามอื่นคำตอบที่ยอมรับได้แนะนำให้แทนที่คำสั่ง if (ถูกมาก) ในโค้ด Python ด้วยบล็อก try / except เพื่อปรับปรุงประสิทธิภาพ

สไตล์การเข้ารหัสมีปัญหากันและสมมติว่าไม่มีการเรียกใช้ข้อยกเว้นจะทำให้มีตัวจัดการข้อยกเว้น (ประสิทธิภาพที่ชาญฉลาด) แตกต่างกันมากน้อยเพียงใดเมื่อเทียบกับการไม่มี if-statement ที่เปรียบเทียบกับศูนย์


6
เมื่อคุณวัดผลคุณได้เรียนรู้อะไร?
ล็อต

1
คำถามที่เกี่ยวข้อง: stackoverflow.com/questions/1835756
tzot

ใช้ลอง / ยกเว้นหากโอกาสในการควบคุมไปที่ยกเว้นบางส่วนน้อยลงและถ้า / อื่น ๆ หากมีโอกาสมากขึ้น
shadow0359

คำตอบ:


115

ทำไมคุณไม่วัดโดยใช้timeitโมดูล ? ด้วยวิธีนี้คุณจะเห็นได้ว่าเกี่ยวข้องกับแอปพลิเคชันของคุณหรือไม่

ตกลงฉันได้ลองทำสิ่งต่อไปนี้แล้ว:

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))

ผลลัพธ์:

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

ดังนั้นตามที่คาดไว้การไม่มีตัวจัดการข้อยกเว้นจะเร็วกว่าเล็กน้อย (แต่จะระเบิดขึ้นที่ใบหน้าของคุณเมื่อเกิดข้อยกเว้น) และtry/exceptเร็วกว่าอย่างชัดเจนifตราบใดที่ไม่เป็นไปตามเงื่อนไข

แต่ทั้งหมดอยู่ในลำดับความสำคัญเดียวกันและไม่น่าจะมีความสำคัญทั้งสองทาง เฉพาะในกรณีที่เป็นไปตามเงื่อนไขจริงifเวอร์ชันนั้นจะเร็วกว่ามาก


3
น่าสนใจ. ดังนั้นtry/exceptจะเร็วกว่าif a != 0
Thilo

12
อ่าเป็นตัวเลือกที่ดีสำหรับคำ: "ทุกอย่างอยู่ในลำดับความสำคัญเดียวกัน" ... ฉันสงสัยว่าหลายคนที่หลีกเลี่ยงข้อยกเว้นคาดหวังว่าพวกเขาจะช้าเป็น 10 เท่า
Garrett Bluma

การรันโค้ดของคุณบน Fedora ด้วย python 2.7.5 แสดงให้เห็นว่าเวอร์ชัน "if" (0.08 usec / pass) เร็วกว่า "try / except" one (0.11 usec / pass) เมื่อ a = 1
duleshi

@duleshi น่าสนใจ. ฉันสงสัยว่ามันเป็น x86 / x64 หรือเปล่า? หรืออาจเป็นส่วนขยายของโปรเซสเซอร์ที่แตกต่างกัน?
พื้นฐาน

60

คำถามนี้มีคำตอบตามความเป็นจริงในคำถามที่พบบ่อยเกี่ยวกับการออกแบบและประวัติ :

บล็อก try / except จะมีประสิทธิภาพมากหากไม่มีการเพิ่มข้อยกเว้น การจับข้อยกเว้นมีราคาแพง


3
ฉันแค่สงสัยว่า "มีประสิทธิภาพมาก" นั้นมีประสิทธิภาพเพียงใด เห็นได้ชัดว่ามันเร็วกว่าแล้วแม้แต่คำสั่ง "if" ที่เรียบง่ายมาก
Thilo

ข้อความที่ตัดตอนมาคุณโพสต์มาจากการออกแบบและประวัติศาสตร์คำถามที่พบบ่อย
nitsas

บางที "มีประสิทธิภาพสูง" อาจหมายถึงสิ่งที่ทำใน Java ?
ebk

19

คำถามนี้ทำให้เข้าใจผิด หากคุณถือว่าข้อยกเว้นไม่ถูกทริกเกอร์ไม่มีรหัสใดที่เหมาะสมที่สุด

หากคุณถือว่าข้อยกเว้นถูกทริกเกอร์เป็นส่วนหนึ่งของเงื่อนไขข้อผิดพลาดแสดงว่าคุณอยู่นอกขอบเขตของการต้องการรหัสที่เหมาะสมที่สุดแล้ว (และคุณอาจไม่ได้จัดการกับข้อยกเว้นในระดับที่ละเอียดเช่นนั้น)

หากคุณกำลังใช้ข้อยกเว้นเป็นส่วนหนึ่งของโฟลว์การควบคุมมาตรฐานซึ่งเป็นวิธี "ขอการให้อภัยไม่อนุญาต" ของ Pythonic ข้อยกเว้นจะถูกทริกเกอร์และค่าใช้จ่ายจะขึ้นอยู่กับประเภทของข้อยกเว้นประเภทของ if และเปอร์เซ็นต์ของเวลาที่คุณประมาณว่าเกิดข้อยกเว้นขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.