ข้อยกเว้นใน C ++ ช้ามาก


99

ฉันกำลังดูSystematic Error Handling ใน C ++ - Andrei Alexandrescuเขาอ้างว่าข้อยกเว้นใน C ++ นั้นช้ามาก

นี่ยังคงเป็นจริงสำหรับ C ++ 98 หรือไม่?


44
ไม่มีเหตุผลที่จะถามว่า "ข้อยกเว้น C ++ 98" เร็วกว่า / ช้ากว่า "ข้อยกเว้น C ++ 03" หรือ "ข้อยกเว้น C ++ 11" หรือไม่ ประสิทธิภาพของพวกเขาขึ้นอยู่กับวิธีการที่คอมไพเลอร์นำมาใช้ในโปรแกรมของคุณและมาตรฐาน C ++ ไม่ได้บอกอะไรเกี่ยวกับวิธีการนำไปใช้ ข้อกำหนดเดียวคือพฤติกรรมของพวกเขาต้องเป็นไปตามมาตรฐาน (กฎ "as-if")
ในซิลิโค

ที่เกี่ยวข้อง (แต่ไม่ซ้ำกันจริงๆ) คำถาม: stackoverflow.com/questions/691168/…
ฟิลิปป์

2
ใช่มันช้ามาก แต่ไม่ควรถูกโยนทิ้งเพื่อการดำเนินงานปกติหรือใช้เป็นสาขา
BЈовић

ฉันได้พบคำถามที่คล้ายกัน
PaperBirdMaster

เพื่อชี้แจงสิ่งที่BЈовићพูดการใช้ข้อยกเว้นไม่ใช่สิ่งที่ต้องกลัว เมื่อเกิดข้อยกเว้นที่คุณต้องเผชิญกับการดำเนินการที่เสียเวลา (อาจ) ฉันอยากรู้เหมือนกันว่าทำไมคุณถึงอยากรู้ C ++ 89 โดยเฉพาะ ... เวอร์ชันล่าสุดคือ C ++ 11 และเวลาที่ใช้ในการเรียกใช้ข้อยกเว้นคือการกำหนดการนำไปใช้งานดังนั้น 'อาจ' ใช้เวลานาน .
thecoshman

คำตอบ:


163

โมเดลหลักที่ใช้ในปัจจุบันสำหรับข้อยกเว้น (Itanium ABI, VC ++ 64 บิต) คือข้อยกเว้นของโมเดล Zero-Cost

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

เมื่อเทียบกับif (error)กลยุทธ์ทั่วไป:

  • แบบจำลอง Zero-Cost ตามชื่อที่แสดงถึงนั้นฟรีเมื่อไม่มีข้อยกเว้นเกิดขึ้น
  • มีค่าใช้จ่ายประมาณ 10x / 20x ifเมื่อมีข้อยกเว้นเกิดขึ้น

อย่างไรก็ตามค่าใช้จ่ายไม่สำคัญที่จะวัด:

  • โดยทั่วไปโต๊ะข้างจะเย็นดังนั้นการดึงข้อมูลจากหน่วยความจำจึงใช้เวลานาน
  • การกำหนดตัวจัดการที่เหมาะสมเกี่ยวข้องกับ RTTI: ตัวบอก RTTI จำนวนมากที่จะดึงข้อมูลกระจัดกระจายไปรอบ ๆ หน่วยความจำและการดำเนินการที่ซับซ้อนในการรัน (โดยทั่วไปจะเป็นการdynamic_castทดสอบสำหรับตัวจัดการแต่ละตัว)

ดังนั้นแคชส่วนใหญ่จึงพลาดและไม่สำคัญเมื่อเทียบกับรหัส CPU บริสุทธิ์

หมายเหตุ: สำหรับรายละเอียดเพิ่มเติมโปรดอ่านรายงาน TR18015 บทที่ 5.4 การจัดการข้อยกเว้น (pdf)

ใช่ข้อยกเว้นจะช้าในเส้นทางพิเศษแต่จะเร็วกว่าการตรวจสอบอย่างชัดเจน ( ifกลยุทธ์) โดยทั่วไป

หมายเหตุ: Andrei Alexandrescu ดูเหมือนจะตั้งคำถามว่า "เร็วกว่า" โดยส่วนตัวแล้วฉันได้เห็นสิ่งต่าง ๆ แกว่งไปมาทั้งสองวิธีบางโปรแกรมทำงานได้เร็วขึ้นโดยมีข้อยกเว้นและโปรแกรมอื่น ๆ เร็วกว่าด้วยสาขาดังนั้นจึงดูเหมือนว่าจะสูญเสียความสามารถในการมองโลกในแง่ดีไปในบางสภาวะ


มันสำคัญหรือไม่?

ฉันจะอ้างว่ามันไม่ ควรเขียนโปรแกรมโดยคำนึงถึงความสามารถในการอ่านไม่ใช่ประสิทธิภาพ (อย่างน้อยไม่ใช่เป็นเกณฑ์แรก) จะใช้ข้อยกเว้นเมื่อคาดว่าผู้โทรไม่สามารถหรือไม่ต้องการจัดการกับความล้มเหลวในจุดนั้นและส่งต่อไปยังสแต็ก โบนัส: ในข้อยกเว้น C ++ 11 สามารถแบ่งระหว่างเธรดโดยใช้ไลบรารีมาตรฐาน

นี่เป็นเรื่องละเอียดอ่อนฉันอ้างว่าmap::findไม่ควรโยน แต่ฉันสบายดีที่map::findจะส่งคืนสิ่งchecked_ptrที่พ่นหากความพยายามที่จะหักล้างมันล้มเหลวเนื่องจากเป็นโมฆะในกรณีหลังเช่นเดียวกับในกรณีของคลาสที่ Alexandrescu แนะนำผู้โทรเลือกระหว่างการตรวจสอบอย่างชัดเจนและการอาศัยข้อยกเว้น การให้อำนาจผู้โทรโดยไม่ให้ความรับผิดชอบมากขึ้นมักเป็นสัญญาณของการออกแบบที่ดี


3
+1 ฉันจะเพิ่มสี่สิ่งเท่านั้น: (0) เกี่ยวกับการสนับสนุนสำหรับการปลูกซ้ำที่เพิ่มใน C ++ 11; (1) การอ้างอิงรายงานของคณะกรรมการเกี่ยวกับประสิทธิภาพ c ++ (2) ข้อสังเกตบางประการเกี่ยวกับความถูกต้อง (เนื่องจากเป็นเรื่องที่น่าเชื่อถือแม้กระทั่งความสามารถในการอ่าน) และ (3) เกี่ยวกับประสิทธิภาพข้อสังเกตเกี่ยวกับการวัดผลเทียบกับกรณีที่ไม่ใช้ข้อยกเว้น (ทั้งหมดเป็นญาติกัน)
ไชโยและ hth - Alf

2
@ Cheersandhth. -Alf: (0), (1) และ (3) done: ขอบคุณ เกี่ยวกับความถูกต้อง (2) ในขณะที่ความสามารถในการอ่านสูงกว่าฉันไม่แน่ใจเกี่ยวกับข้อยกเว้นที่นำไปสู่รหัสที่ถูกต้องมากกว่ากลยุทธ์การจัดการข้อผิดพลาดอื่น ๆ (มันง่ายมากที่จะลืมเกี่ยวกับเส้นทางที่มองไม่เห็นของข้อยกเว้นการดำเนินการที่สร้างขึ้น)
Matthieu M.

2
คำอธิบายอาจถูกต้องในพื้นที่ แต่อาจเป็นที่น่าสังเกตว่าการมีข้อยกเว้นมีผลกระทบทั่วโลกเกี่ยวกับสมมติฐานและการเพิ่มประสิทธิภาพที่คอมไพลเลอร์สามารถทำได้ ผลกระทบเหล่านี้ประสบปัญหาที่ "ไม่มีตัวอย่างการตอบโต้ที่ไม่สำคัญ" เนื่องจากคอมไพเลอร์สามารถมองเห็นผ่านโปรแกรมขนาดเล็กได้เสมอ การสร้างโปรไฟล์บนฐานรหัสขนาดใหญ่ที่สมจริงโดยมีและไม่มีข้อยกเว้นอาจเป็นความคิดที่ดี
Kerrek SB

4
> โมเดล Zero-Cost ตามชื่อที่แสดงถึงนั้นไม่มีค่าใช้จ่ายเมื่อไม่มีข้อยกเว้นเกิดขึ้นสิ่งนี้ไม่ได้เป็นความจริงในระดับรายละเอียดที่ดีที่สุด การสร้างโค้ดเพิ่มเติมจะส่งผลกระทบต่อประสิทธิภาพเสมอแม้ว่าจะมีขนาดเล็กและละเอียดอ่อนก็ตาม ... ระบบปฏิบัติการอาจใช้เวลานานกว่าเล็กน้อยในการโหลดไฟล์ปฏิบัติการหรือคุณจะพลาด i-cache มากขึ้น แล้วสแต็คคลายรหัสล่ะ? แล้วการทดลองที่คุณสามารถทำได้เพื่อวัดผลแทนที่จะพยายามทำความเข้าใจด้วยความคิดที่มีเหตุผลล่ะ?
jheriko

2
@jheriko: ฉันเชื่อว่าฉันตอบคำถามส่วนใหญ่ของคุณไปแล้วจริงๆ เวลาในการโหลดไม่ควรได้รับผลกระทบ (ไม่ควรโหลดโค้ดเย็น) i-cache ไม่ควรได้รับผลกระทบ (โค้ดเย็นไม่ควรทำให้เป็น i-cache) ... ดังนั้นเพื่อตอบคำถามที่ขาดหายไปหนึ่งข้อ: "วิธีการวัด" => การแทนที่ข้อยกเว้นใด ๆ ที่เกิดขึ้นด้วยการเรียกที่abortจะช่วยให้คุณสามารถวัดขนาดไบนารีและตรวจสอบว่าเวลาโหลด / i-cache ทำงานในลักษณะเดียวกัน แน่นอนดีกว่าไม่ตีใด ๆabort...
Matthieu M.

61

เมื่อคำถามถูกโพสต์ฉันกำลังเดินทางไปหาหมอโดยมีแท็กซี่รออยู่ฉันจึงมีเวลาเพียงแค่แสดงความคิดเห็นสั้น ๆ แต่ตอนนี้มีการแสดงความคิดเห็นและโหวตและโหวตแล้วฉันควรเพิ่มคำตอบของตัวเอง แม้ว่าคำตอบของ Matthieuจะค่อนข้างดีอยู่แล้ว


ข้อยกเว้นใน C ++ ช้าเป็นพิเศษเมื่อเทียบกับภาษาอื่น ๆ หรือไม่?

อ้างสิทธิ์อีกครั้ง

"ฉันกำลังดูการจัดการข้อผิดพลาดอย่างเป็นระบบใน C ++ - Andrei Alexandrescuเขาอ้างว่าข้อยกเว้นใน C ++ นั้นช้ามาก"

หากนั่นคือสิ่งที่ Andrei อ้างตามตัวอักษรแล้วครั้งหนึ่งเขาก็ทำให้เข้าใจผิดอย่างมากหากไม่ผิดอย่างจริงจัง สำหรับยก / ข้อยกเว้นโยนมักจะช้าเมื่อเทียบกับการดำเนินงานพื้นฐานอื่น ๆ ในภาษาที่ไม่คำนึงถึงการเขียนโปรแกรมภาษา ไม่ใช่แค่ใน C ++ หรือมากกว่าใน C ++ มากกว่าภาษาอื่น ๆ ตามที่อ้างว่าอ้างว่าระบุไว้

โดยทั่วไปโดยทั่วไปโดยไม่คำนึงถึงภาษาคุณลักษณะพื้นฐานของภาษาทั้งสองที่มีลำดับความสำคัญช้ากว่าที่เหลือเนื่องจากแปลเป็นการเรียกประจำที่จัดการโครงสร้างข้อมูลที่ซับซ้อนคือ

  • ยกเว้นการขว้างปาและ

  • การจัดสรรหน่วยความจำแบบไดนามิก

อย่างมีความสุขใน C ++ เรามักจะหลีกเลี่ยงทั้งรหัสเวลาที่สำคัญ

น่าเสียดายที่ไม่มีสิ่งเช่นนี้เป็นอาหารกลางวันฟรีแม้ว่าประสิทธิภาพเริ่มต้นของ C ++ จะค่อนข้างใกล้เคียง :-) เพื่อประสิทธิภาพที่ได้รับจากการหลีกเลี่ยงการโยนข้อยกเว้นและการจัดสรรหน่วยความจำแบบไดนามิกโดยทั่วไปทำได้โดยการเข้ารหัสที่ระดับนามธรรมที่ต่ำกว่าโดยใช้ C ++ เป็นเพียง "C ที่ดีกว่า" และความเป็นนามธรรมที่ต่ำลงหมายถึง“ ความซับซ้อน” ที่มากขึ้น

ความซับซ้อนที่มากขึ้นหมายถึงการใช้เวลาในการบำรุงรักษามากขึ้นและผลประโยชน์เพียงเล็กน้อยจากการใช้โค้ดซ้ำซึ่งเป็นต้นทุนทางการเงินที่แท้จริงแม้ว่าจะประเมินหรือวัดได้ยากก็ตาม กล่าวคือด้วย C ++ หนึ่งสามารถแลกเปลี่ยนประสิทธิภาพของโปรแกรมเมอร์บางส่วนเพื่อประสิทธิภาพในการดำเนินการได้หากต้องการ การที่จะทำเช่นนั้นส่วนใหญ่เป็นการตัดสินใจทางวิศวกรรมและทางความรู้สึกเพราะในทางปฏิบัติมีเพียงผลกำไรไม่ใช่ต้นทุนเท่านั้นที่สามารถประมาณและวัดผลได้ง่าย


มีมาตรการตามวัตถุประสงค์ของประสิทธิภาพการขว้างข้อยกเว้น C ++ หรือไม่?

ใช่ c ++ คณะกรรมการมาตรฐานสากลมีการเผยแพร่รายงานด้านเทคนิคเกี่ยวกับ C ++ ประสิทธิภาพ TR18015


มันจะมีอะไรหมายความว่าข้อยกเว้น“ช้า”?

ส่วนใหญ่หมายความว่าthrowอาจใช้เวลานานมาก™เมื่อเทียบกับงานเช่นintงานที่มอบหมายเนื่องจากการค้นหาตัวจัดการ

ดังที่ TR18015 กล่าวถึงในหัวข้อ 5.4“ ข้อยกเว้น” มีกลยุทธ์การดำเนินการจัดการข้อยกเว้นหลักสองประการ

  • วิธีการที่แต่ละtryบล็อกตั้งค่าการจับข้อยกเว้นแบบไดนามิกเพื่อให้การค้นหาห่วงโซ่ไดนามิกของตัวจัดการดำเนินการเมื่อมีการโยนข้อยกเว้นและ

  • วิธีการที่คอมไพลเลอร์สร้างตารางการค้นหาแบบคงที่ซึ่งใช้เพื่อกำหนดตัวจัดการสำหรับข้อยกเว้นที่ถูกโยนทิ้ง

แนวทางแรกที่ยืดหยุ่นและทั่วไปเกือบจะถูกบังคับใน Windows 32 บิตในขณะที่ในที่ดิน 64 บิตและใน * nix-land มักใช้วิธีที่สองที่มีประสิทธิภาพมากกว่า

ตามที่รายงานกล่าวถึงสำหรับแต่ละแนวทางมีสามประเด็นหลักที่การจัดการข้อยกเว้นส่งผลกระทบต่อประสิทธิภาพ:

  • try- บล็อก

  • ฟังก์ชันปกติ (โอกาสในการเพิ่มประสิทธิภาพ) และ

  • throw- การแสดงออก

โดยหลักแล้วด้วยวิธีการจัดการข้อยกเว้นแบบไดนามิก (Windows 32 บิต) มีผลกระทบต่อtryบล็อกโดยส่วนใหญ่ไม่คำนึงถึงภาษา (เนื่องจากสิ่งนี้ถูกบังคับโดยรูปแบบการจัดการข้อยกเว้นที่มีโครงสร้างของ Windows ) ในขณะที่วิธีตารางแบบคงที่มีค่าใช้จ่ายประมาณเป็นศูนย์สำหรับtry- บล็อก การพูดคุยเรื่องนี้จะใช้พื้นที่และการค้นคว้ามากกว่าที่จะเป็นจริงสำหรับคำตอบ SO ดังนั้นโปรดดูรายละเอียดในรายงาน

น่าเสียดายที่รายงานจากปี 2549 มีการลงวันที่เล็กน้อยเมื่อปลายปี 2555 และเท่าที่ฉันรู้ว่าไม่มีอะไรเทียบได้ที่ใหม่กว่า

มุมมองที่สำคัญอีกประการหนึ่งคือผลกระทบของการใช้ข้อยกเว้นต่อประสิทธิภาพนั้นแตกต่างอย่างมากจากประสิทธิภาพที่แยกได้ของคุณลักษณะภาษาที่รองรับเนื่องจากตามที่รายงานบันทึกไว้

“ เมื่อพิจารณาถึงการจัดการข้อยกเว้นต้องเปรียบเทียบกับวิธีอื่นในการจัดการกับข้อผิดพลาด”

ตัวอย่างเช่น:

  • ค่าบำรุงรักษาเนื่องจากรูปแบบการเขียนโปรแกรมที่แตกต่างกัน (ความถูกต้อง)

  • การifตรวจสอบความล้มเหลวของไซต์การโทรซ้ำซ้อนเทียบกับส่วนกลางtry

  • ปัญหาในการแคช (เช่นรหัสที่สั้นกว่าอาจพอดีกับแคช)

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


วิธีที่ดีในการหลีกเลี่ยงค่าใช้จ่ายของข้อยกเว้นคืออะไร?

ความถูกต้องมักจะสำคัญกว่าประสิทธิภาพ

สิ่งต่อไปนี้สามารถเกิดขึ้นได้อย่างง่ายดายโดยไม่มีข้อยกเว้น:

  1. รหัส P บางตัวมีไว้เพื่อรับทรัพยากรหรือคำนวณข้อมูลบางอย่าง

  2. รหัสการโทร C ควรตรวจสอบความสำเร็จ / ล้มเหลว แต่ไม่ได้

  3. ทรัพยากรที่ไม่มีอยู่จริงหรือข้อมูลที่ไม่ถูกต้องถูกใช้ในโค้ดตามหลัง C ทำให้เกิดการทำร้ายร่างกายโดยทั่วไป

ปัญหาหลักคือจุด (2) โดยที่รหัสส่งคืนตามปกติรหัสการโทร C จะไม่ถูกบังคับให้ตรวจสอบ

มีสองวิธีหลักที่บังคับให้ตรวจสอบดังกล่าว:

  • โดยที่ P จะโยนข้อยกเว้นเมื่อล้มเหลวโดยตรง

  • โดยที่ P ส่งคืนอ็อบเจ็กต์ที่ C ต้องตรวจสอบก่อนใช้ค่าหลัก (มิฉะนั้นจะเป็นข้อยกเว้นหรือการยุติ)

แนวทางที่สองคือ AFAIK อธิบายโดย Barton และ Nackman เป็นครั้งแรกในหนังสือของพวกเขา * C ++ ทางวิทยาศาสตร์และวิศวกรรม: บทนำด้วยเทคนิคขั้นสูงและตัวอย่างซึ่งพวกเขาแนะนำคลาสที่เรียกว่าFallowผลลัพธ์ของฟังก์ชัน "เป็นไปได้" optionalขณะนี้มีคลาสที่คล้ายกันซึ่งเรียกว่าไลบรารี Boost และคุณสามารถใช้Optionalคลาสด้วยตัวเองได้อย่างง่ายดายโดยใช้std::vectoras value carrier สำหรับกรณีของผลลัพธ์ที่ไม่ใช่ POD

ด้วยแนวทางแรกรหัสการโทร C ไม่มีทางเลือกอื่นนอกจากใช้เทคนิคการจัดการข้อยกเว้น อย่างไรก็ตามด้วยแนวทางที่สองรหัสการเรียก C สามารถตัดสินใจได้เองว่าจะทำการifตรวจสอบตามหรือการจัดการข้อยกเว้นทั่วไป ดังนั้นแนวทางที่สองสนับสนุนการทำให้โปรแกรมเมอร์เทียบกับการแลกเปลี่ยนประสิทธิภาพเวลาดำเนินการ


อะไรคือผลกระทบของมาตรฐาน C ++ ต่างๆเกี่ยวกับประสิทธิภาพการทำงานของข้อยกเว้น?

“ ฉันอยากรู้ว่านี่ยังเป็นจริงสำหรับ C ++ 98”

C ++ 98 เป็นมาตรฐาน C ++ แรก สำหรับข้อยกเว้นนั้นได้นำเสนอลำดับชั้นมาตรฐานของคลาสข้อยกเว้น (น่าเสียดายที่ค่อนข้างไม่สมบูรณ์) ผลกระทบหลักต่อประสิทธิภาพคือความเป็นไปได้ของข้อกำหนดข้อยกเว้น (ลบออกใน C ++ 11) ซึ่งไม่เคยนำไปใช้อย่างสมบูรณ์โดยคอมไพเลอร์ Windows C ++ หลัก Visual C ++: Visual C ++ ยอมรับไวยากรณ์ข้อกำหนดข้อยกเว้น C ++ 98 แต่เพียงละเว้น ข้อกำหนดข้อยกเว้น

C ++ 03 เป็นเพียงองค์ประกอบทางเทคนิคของ C ++ 98 เท่านั้นจริงๆใหม่ใน C ++ 03 คือการเริ่มต้นค่า ซึ่งไม่มีอะไรเป็นข้อยกเว้น.

ด้วยข้อกำหนดข้อยกเว้นทั่วไปมาตรฐาน C ++ 11 ถูกลบออกและแทนที่ด้วยnoexceptคีย์เวิร์ด

มาตรฐาน C ++ 11 ยังเพิ่มการสนับสนุนสำหรับการจัดเก็บและการเปลี่ยนข้อยกเว้นซึ่งเหมาะอย่างยิ่งสำหรับการเผยแพร่ข้อยกเว้น C ++ ในการเรียกกลับของภาษา C การสนับสนุนนี้ จำกัด วิธีการจัดเก็บข้อยกเว้นปัจจุบันอย่างมีประสิทธิภาพ อย่างไรก็ตามเท่าที่ฉันรู้ว่าไม่มีผลต่อประสิทธิภาพการทำงานยกเว้นในระดับที่ในการจัดการข้อยกเว้นโค้ดรุ่นใหม่อาจใช้งานได้ง่ายขึ้นทั้งสองด้านของการเรียกกลับภาษา C


7
"ข้อยกเว้นจะช้าเสมอเมื่อเทียบกับการดำเนินการขั้นพื้นฐานอื่น ๆ ในภาษาโดยไม่คำนึงถึงภาษาโปรแกรม" ... ยกเว้นในภาษาที่ออกแบบมาเพื่อรวบรวมการใช้ข้อยกเว้นในการควบคุมการไหลธรรมดา
Ben Voigt

5
"การโยนข้อยกเว้นเกี่ยวข้องกับทั้งการจัดสรรและการคลี่คลายสแต็ก" เห็นได้ชัดว่าไม่เป็นความจริงโดยทั่วไปและอีกครั้ง OCaml เป็นตัวอย่างตอบโต้ ในภาษาที่รวบรวมขยะไม่จำเป็นต้องคลายสแต็กเนื่องจากไม่มีตัวทำลายดังนั้นคุณจึงlongjmpต้องใช้ตัวจัดการ
JD

2
@JonHarrop: คุณคงไม่รู้ว่า Pyhon มีประโยคสุดท้ายสำหรับการจัดการข้อยกเว้น ซึ่งหมายความว่าการใช้งาน Python มีการคลายสแต็กหรือไม่ใช่ Python ดูเหมือนว่าคุณจะไม่รู้เรื่องที่คุณอ้าง (แฟนตาซี) เลย ขอโทษ.
ไชโยและ hth - Alf

2
@ Cheersandhth. -Alf: "Pyhon มีประโยคสุดท้ายสำหรับการจัดการข้อยกเว้นซึ่งหมายความว่าการใช้งาน Python อาจมีการคลายสแต็กหรือไม่ใช่ Python" try..finallyสร้างสามารถดำเนินการได้โดยไม่ต้องคลี่คลายสแต็ค F #, C # และ Java ทั้งหมดใช้งานได้try..finallyโดยไม่ต้องใช้การคลายสแต็ก คุณเป็นเพียงlongjmpผู้จัดการ (ตามที่ฉันได้อธิบายไปแล้ว)
JD

4
@JonHarrop: คุณฟังดูเหมือนขึ้นเขียง แต่มันก็มีความเกี่ยวข้องฉันสามารถดูสิ่งที่กล่าวถึงเพื่อให้ห่างไกลและจนถึงขณะนี้คุณได้โพสต์ลำดับที่ยาวนานของเชิงลบที่ทำให้เกิดเสียงเรื่องไร้สาระ ฉันจะต้องเชื่อใจคุณเพื่อที่จะเห็นด้วยหรือไม่ใช้ถ้อยคำที่คลุมเครือเพราะในฐานะที่เป็นปฏิปักษ์คุณกำลังเลือกสิ่งที่คุณจะเปิดเผยว่ามัน "หมายความว่า" และแน่นอนฉันไม่เชื่อใจคุณหลังจากเรื่องไร้สาระที่ไร้ความหมายการลงคะแนน ฯลฯ
ไชโยและ hth - Alf

14

คุณไม่สามารถอ้างสิทธิ์เกี่ยวกับประสิทธิภาพได้เว้นแต่คุณจะแปลงรหัสเป็นแอสเซมบลีหรือเปรียบเทียบ

นี่คือสิ่งที่คุณเห็น: (ม้านั่งด่วน)

รหัสข้อผิดพลาดไม่ไวต่อเปอร์เซ็นต์ของการเกิดขึ้น ข้อยกเว้นมีค่าใช้จ่ายเล็กน้อยตราบเท่าที่ไม่เคยโยนทิ้ง เมื่อคุณโยนมันความทุกข์ยากก็เริ่มต้นขึ้น ในตัวอย่างนี้จะโยน 0%, 1%, 10%, 50% และ 90% ของเคส เมื่อข้อยกเว้นถูกโยน 90% ของเวลารหัสจะช้ากว่ากรณีที่มีการโยนข้อยกเว้น 10% ถึง 8 เท่า อย่างที่คุณเห็นข้อยกเว้นนั้นช้ามาก อย่าใช้หากโยนบ่อยๆ หากแอปพลิเคชันของคุณไม่มีข้อกำหนดแบบเรียลไทม์อย่าลังเลที่จะโยนพวกเขาหากเกิดขึ้นน้อยมาก

คุณเห็นความคิดเห็นที่ขัดแย้งกันมากมายเกี่ยวกับพวกเขา แต่สุดท้ายมีข้อยกเว้นช้าหรือไม่? ฉันไม่ตัดสิน. เพียงแค่ดูเกณฑ์มาตรฐาน

เกณฑ์มาตรฐานประสิทธิภาพข้อยกเว้นของ C ++


13

มันขึ้นอยู่กับคอมไพเลอร์

ตัวอย่างเช่น GCC เป็นที่ทราบกันดีว่ามีประสิทธิภาพต่ำมากเมื่อจัดการกับข้อยกเว้น แต่สิ่งนี้ดีขึ้นมากในช่วงไม่กี่ปีที่ผ่านมา

แต่โปรดทราบว่าข้อยกเว้นในการจัดการควรเป็นข้อยกเว้นมากกว่ากฎในการออกแบบซอฟต์แวร์ของคุณ เมื่อคุณมีแอปพลิเคชันที่มีข้อยกเว้นมากมายต่อวินาทีซึ่งส่งผลกระทบต่อประสิทธิภาพการทำงานและยังถือว่าเป็นการทำงานปกติคุณควรคิดที่จะทำสิ่งต่างๆ

ข้อยกเว้นเป็นวิธีที่ยอดเยี่ยมในการทำให้โค้ดอ่านง่ายขึ้นโดยนำโค้ดที่จัดการข้อผิดพลาดที่ไม่เป็นระเบียบออกไปให้พ้นทาง แต่ทันทีที่มันกลายเป็นส่วนหนึ่งของโฟลว์โปรแกรมปกติพวกเขาก็ยากที่จะปฏิบัติตาม จำไว้ว่า a throwค่อนข้างgoto catchปลอมตัว


-1 เป็นคำถามที่เกิดขึ้นในตอนนี้ "นี่ยังคงเป็นจริงสำหรับ C ++ 98" ซึ่งไม่ได้ขึ้นอยู่กับคอมไพเลอร์อย่างแน่นอน นอกจากนี้คำตอบนี้ก็throw new Exceptionคือ Java-ism ตามกฎแล้วไม่ควรโยนพอยน์เตอร์
ไชโยและ hth - Alf

1
มาตรฐาน 98 กำหนดไว้อย่างชัดเจนว่าจะนำข้อยกเว้นไปใช้อย่างไร?
thecoshman

6
C ++ 98 เป็นมาตรฐาน ISO ไม่ใช่คอมไพเลอร์ มีคอมไพเลอร์จำนวนมากที่ใช้งานได้
ฟิลิปป์

3
@thecoshman: ไม่มาตรฐาน C ++ ไม่ได้บอกว่าจะต้องดำเนินการอย่างไร (ยกเว้นส่วน "ขีด จำกัด การนำไปใช้" ของมาตรฐานที่เป็นไปได้)
ในซิลิโค

2
@Insilico ฉันสามารถวาดข้อสรุปเชิงตรรกะได้ว่า (น่าตกใจ) มีการกำหนดการนำไปใช้งาน (อ่านเฉพาะคอมไพเลอร์) ว่าข้อยกเว้นดำเนินการอย่างไร
thecoshman

4

ใช่ แต่นั่นไม่สำคัญ ทำไม?
อ่านสิ่งนี้:
https://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx

โดยทั่วไปแล้วที่บอกว่าการใช้ข้อยกเว้นอย่าง Alexandrescu อธิบายไว้ (การชะลอตัว 50x เพราะใช้catchเป็นelse) นั้นไม่ถูกต้อง ที่กล่าวไว้สำหรับคนที่ชอบทำแบบนั้นฉันหวังว่า C ++ 22 :) จะเพิ่มสิ่งที่ต้องการ:
(โปรดทราบว่านี่จะต้องเป็นภาษาหลักเนื่องจากโดยทั่วไปแล้วคอมไพเลอร์สร้างโค้ดจากที่มีอยู่)

result = attempt<lexical_cast<int>>("12345");  //lexical_cast is boost function, 'attempt'
//... is the language construct that pretty much generates function from lexical_cast, generated function is the same as the original one except that fact that throws are replaced by return(and exception type that was in place of the return is placed in a result, but NO exception is thrown)...     
//... By default std::exception is replaced, ofc precise configuration is possible
if (result)
{
     int x = result.get(); // or result.result;
}
else 
{
     // even possible to see what is the exception that would have happened in original function
     switch (result.exception_type())
     //...

}

ป.ล. โปรดทราบว่าแม้ว่าข้อยกเว้นจะช้าขนาดนั้น ... ก็ไม่ใช่ปัญหาหากคุณไม่ใช้เวลาส่วนนั้นมากในโค้ดระหว่างการดำเนินการ ... ตัวอย่างเช่นถ้าการแบ่ง float ช้าและคุณทำให้เป็น 4x เร็วกว่านั้นไม่สำคัญว่าคุณจะใช้เวลา 0.3% ในการหาร FP ...


0

เช่นเดียวกับในซิลิโคกล่าวว่าการใช้งานขึ้นอยู่กับ แต่โดยทั่วไปแล้วข้อยกเว้นนั้นถือว่าช้าสำหรับการนำไปใช้งานใด ๆ และไม่ควรใช้ในโค้ดที่เน้นประสิทธิภาพ

แก้ไข: ฉันไม่ได้บอกว่าอย่าใช้เลย แต่สำหรับโค้ดที่เน้นประสิทธิภาพควรหลีกเลี่ยง


9
นี่เป็นวิธีที่ง่ายที่สุดในการดูประสิทธิภาพข้อยกเว้น ตัวอย่างเช่น GCC ใช้การติดตั้งแบบ "ศูนย์ต้นทุน" ซึ่งคุณจะไม่ได้รับผลกระทบด้านประสิทธิภาพหากไม่มีข้อยกเว้นใด ๆ เกิดขึ้น และข้อยกเว้นมีไว้สำหรับสถานการณ์พิเศษ (เช่นหายาก) ดังนั้นแม้ว่าเมตริกบางส่วนจะช้า แต่ก็ยังไม่มีเหตุผลเพียงพอที่จะไม่ใช้
ในซิลิโค

@insilico ถ้าคุณดูว่าทำไมฉันถึงพูดฉันไม่ได้บอกว่าอย่าใช้ข้อยกเว้นเต็มหยุด ฉันระบุรหัสเร่งรัดประสิทธิภาพนี่คือการประเมินที่ถูกต้องฉันทำงานกับ gpgpus เป็นหลักและฉันจะถูกยิงหากฉันใช้ข้อยกเว้น
Chris McCabe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.