Talk at RailsWorld: Presented about eliminating allocations in tokenizers and showed a function to measure allocations.
- Allocation measurement function:
def allocations; x = GC.stat(:total_allocated_objects); yield; GC.stat(:total_allocated_objects) - x; end
- Examples of non-allocating code: Booleans, nil, symbols, integers, floats are represented as "tagged pointers" and don't allocate.
- Examples of sometimes allocating code: Math on integers depends on the number size, and string literals depend on
frozen_string_literal
setting. - Examples of always allocating code: Arrays, hashes, objects, string slices, etc. allocate an object.
- Allocation measurement function:
Shopify after-party question: RuboCop rule says to use
[x, y].max
for min or max calculations, but it seems wasteful as it allocates an array.- Compiler's perspective: Knows the array literal is ephemeral, allocates on the stack, does the calculation, and throws away the array.
- Instruction sequence example:
opt_newarray_send
instruction is used, which checks for monkey patches and calls the appropriatemax
function. - Confirming no allocation: Using the
allocations
function shows thefoo
method doesn't allocate.
- Aaron's Opinion Corner: Linter should explain why a rule is a rule. In this case, the performance-related rule may not be necessary as idiomatic Ruby is often performant. But there are cases where non-idiomatic code is needed for performance.
- More Stuff:
Array#max
isn't the only method using this trick. It also works withArray#min
,Array#pack
, andArray#hash
. But CRuby won't apply the optimization in all cases, like when there is aduparray
instruction. Manually inlining simple cases like[3, 4].max
to4
is a workaround. These optimizations are context-dependent and prescribing more optimal code can be complex. Language servers can suggest faster code as a teaching opportunity.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。