Skip to content

Instantly share code, notes, and snippets.

@maxim
Last active May 13, 2023 12:17
Show Gist options
  • Save maxim/58105aa34f18b64cd2583fe1c857c060 to your computer and use it in GitHub Desktop.
Save maxim/58105aa34f18b64cd2583fe1c857c060 to your computer and use it in GitHub Desktop.
Catch throw vs raise rescue vs baseline return (Ruby v3.2.0)
code1 = -> { catch(:foo) { throw(:foo, 'string') } }
code2 = -> { begin; raise RuntimeError; rescue RuntimeError; 'string' end }
code3 = -> { 'string' }
Benchmark.ips do |x|
x.report("catch a throw") {
value = code1.call
}
x.report("rescue and exception") {
value = code2.call
}
x.report("return string") {
value = code3.call
}
x.compare!
end
# Warming up --------------------------------------
# catch a throw 347.786k i/100ms
# rescue and exception 135.262k i/100ms
# return string 795.463k i/100ms
# Calculating -------------------------------------
# catch a throw 3.465M (± 0.4%) i/s - 17.389M in 5.019335s
# rescue and exception 1.359M (± 2.0%) i/s - 6.898M in 5.077732s
# return string 7.949M (± 0.4%) i/s - 39.773M in 5.003773s
# Comparison:
# return string: 7948778.8 i/s
# catch a throw: 3464519.8 i/s - 2.29x slower
# rescue and exception: 1359120.9 i/s - 5.85x slower
@silent-e
Copy link

I've investigated this and I think there's a flaw in this code. I'm not sure code is being reassigned correctly between tests. raise/rescue should still be 3x slower even in 3.2. 2x slower if you ignore the backtrace. Try my gist where I numbered each code block. Your results seemed unexpected given other recent reporting.

@maxim
Copy link
Author

maxim commented May 13, 2023

@silent-e Great find. Wow what a weird behavior with variables. Updated the bench.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment