Return nil from assignment benchmarks #50
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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: