How expensive is it to create Procs and lambdas in ruby?
(answer: not expensive)
I recently implemented fancier around callbacks for ruby-clock. To do this sort of thing, you need to generate a Proc or lambda on the fly, so that each subsequent callback has something to .call
. Procs and lambdas can't accept a block, so that's the only way to do it. Which is also a bit educational because you sort of end up implementing blocks in the process.
I'm fairly certain this is the only way. Here's how I did it. Here's how rails does it, although I admit I did not invest time into understanding this code.
After successfully implementing this I got curious if there were any performance concerns with generating Procs. So here's a simple benchmark, testing how much overhead there is to create and invoke Procs and lambdas:
t = Time.now
10_000_000.times {1+1}
puts Time.now - t
t = Time.now
10_000_000.times {lambda{1+1}.call}
puts Time.now - t
t = Time.now
10_000_000.times {Proc.new{ 1+1 }.call}
puts Time.now - t
0.206395
1.670558
1.915812
(I was too lazy to use the benchmark library, do a warmup, etc. but I did do a quick check with putting them in a different order and the results were identical.)
So there you have it - don't worry about the overhead of using Procs and lambdas.
Looks like lambdas are slightly more performant than Procs. I went with Procs because I think of them as "a block turned into an object", and that's the vibe here. I didn't think this through at the time. but I think I also prefer the Proc behavior of a return
taking over the calling context. This maybe gives the opportunity for an around hook to halt progress (e.g. an around hook which sometimes decide that a job shouldn't run at all). I'll experiment with this eventually and maybe document it as a feature.