Closed haileys closed 9 years ago
@charliesome Thank you for your detailed explanations. :bow: I was so wrong :sweat:
So now the fast one is called slow and vice versa, right?
@etiennebarrie Oh heh, yeah I forgot to update that
@etiennebarrie Fixed in https://github.com/JuanitoFatas/fast-ruby/commit/53894bf4e7c91af36a27a65cc0ae2decd368a743, thanks!
The parallel assignment benchmark only allocates an array because the assignment expression is the last expression in the method (and so its result is returned to the caller). If Ruby detects that an expression's result is unused (as would be the case with most assignment expressions), it will avoid allocating the array and just assign directly.
Inspecting the bytecode generated for parallel assignment in both cases shows off this optimisation:
In the first bytecode dump, Ruby has no option but to allocate the array because the assignment expression is the last expression. Even still, we can see that the Ruby VM is still clever enough to see that each element in the array has no evaluation side effects and so it is able to just dup an pre-allocated array rather than building a new one up from scratch.
In the second bytecode dump, because the assignment is not the last expression and does not need to return a value, the Ruby VM takes a shortcut and just assigns the variables directly rather than creating an array. In fact, this is even faster than splitting these assignments out over multiple lines because the compiler does not need to emit a per-line
trace
instruction for each assignment.Here's the benchmark results before changing the benchmarked methods to return
nil
:The benchmark results after changing the benchmarked methods to return
nil
show a clear improvement in favour of parallel assignment: