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_literalsetting. - 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].maxfor 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_sendinstruction is used, which checks for monkey patches and calls the appropriatemaxfunction. - Confirming no allocation: Using the
allocationsfunction shows thefoomethod 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#maxisn'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 aduparrayinstruction. Manually inlining simple cases like[3, 4].maxto4is 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) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。