ฉันเคยสงสัยมาโดยตลอดว่าข้อยกเว้นในทับทิมจะช้าเมื่อเทียบกับกลไกการควบคุมการไหลอื่นๆ ท้ายที่สุด ข้อยกเว้นนั้นซับซ้อนกว่าการ "พัก" หรือ "การส่งคืน" ธรรมดาๆ มาก แต่ฉันเคยมีลางสังหรณ์ผิดมาก่อน เลยคิดว่าจะลองทดสอบดู
ในโค้ดด้านล่าง ฉันกำลังใช้เบนช์มาร์ก-ips gem เพื่อเปรียบเทียบประสิทธิภาพสัมพัทธ์ของการออกจากลูปผ่านข้อยกเว้น ตัวแบ่ง และส่งคืน ฉันเคยเห็นตัวอย่างบนเว็บของผู้คนที่ทำการวัดประสิทธิภาพแบบนี้กับ mri 1.9 แต่ฉันอยากลองกับ mri 2.2
require 'benchmark/ips'
def exit_via_exception
5.times do
raise RuntimeError
end
rescue
end
def exit_via_break
5.times do
break
end
end
def exit_via_return
5.times do
return
end
end
Benchmark.ips do |x|
x.report("exception") { exit_via_exception }
x.report("break") { exit_via_break }
x.report("return") { exit_via_return }
end
ผลลัพธ์ที่ได้ค่อนข้างส่าย ฟังก์ชันที่ใช้ข้อยกเว้นนั้นเร็วกว่าครึ่งหนึ่งที่ใช้ฟังก์ชัน break and return
$ ruby exception_benchmark.rb
Calculating -------------------------------------
exception 50.872k i/100ms
break 125.322k i/100ms
return 124.173k i/100ms
-------------------------------------------------
exception 714.795k (± 2.7%) i/s - 3.612M
break 3.459M (± 3.1%) i/s - 17.294M
return 3.379M (± 3.0%) i/s - 16.888M
นี่ไม่ใช่เกณฑ์มาตรฐานที่สมบูรณ์แบบ
มีบางประเด็นที่ฉันไม่แน่ใจว่าจะชดเชยอย่างไร ตัวอย่างเช่น ต้องส่งคืนวิธี exception และ break ดังนั้นพวกเขากำลังทำมากกว่าวิธีที่เพียงแค่ส่งคืน นอกจากนี้ ฉันสนใจที่จะดูว่าการช่วยเหลือข้อยกเว้นนี้เพิ่มค่าใช้จ่ายด้านประสิทธิภาพหรือไม่ แต่การไม่ช่วยเหลือจะทำให้เกณฑ์มาตรฐานถูกยกเลิก
ถึงกระนั้น ข้อยกเว้นก็ช้ากว่าตัวอย่างอื่นๆ มาก ซึ่งฉันคิดว่าผลลัพธ์นั้นมีความหมายแม้ว่าจะไม่ได้สมบูรณ์แบบก็ตาม
บทเรียนที่เราได้เรียนรู้?
หากคุณกำลังใช้ข้อยกเว้นเป็นกลไกควบคุมการไหล หยุดเดี๋ยวนี้! โดยเฉพาะอย่างยิ่งถ้าคุณมีการวนซ้ำที่ประกอบด้วยข้อยกเว้นที่ถูกยกและจับซ้ำแล้วซ้ำอีก
สิ่งนี้จะเปลี่ยนวิธีที่ฉันใช้ข้อยกเว้นเป็นการส่วนตัวหรือไม่ อาจจะไม่. ฉันสามารถอยู่กับความช้าเล็กน้อยได้หากความช้านั้นเป็นข้อยกเว้นของกฎ :)
...แล้ว JRuby และ RBx ล่ะ?
Josh Cheek (@josh_cheek บนทวิตเตอร์) เขียนเวอร์ชันของตัวเองของเกณฑ์มาตรฐานนี้ซึ่งครอบคลุมมากกว่าของฉัน และเขาต่อต้านการนำทับทิมมาใช้หลายครั้ง คุณสามารถดูผลลัพธ์ของเขาได้ที่นี่ เห็นได้ชัดว่าการแบ่งยังคงเป็นผู้ชนะ :)