mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-17 01:40:42 -07:00
31 lines
1.9 KiB
Markdown
31 lines
1.9 KiB
Markdown
# Autoresearch Ideas
|
|
|
|
## Dead Ends (tried and failed)
|
|
|
|
- **Tag name interning** (skip+byte dispatch): saves 878 allocs but verification loop overhead kills speed
|
|
- **String dedup (-@)** for filter names: no alloc savings, creates temp strings anyway
|
|
- **Split-based tokenizer**: 2.5x faster C-level split but can't handle {{ followed by %} nesting
|
|
- **Streaming tokenizer**: needs own StringScanner (+alloc), per-shift overhead worse than eager array
|
|
- **Merge simple_lookup? into initialize**: logic overhead offsets saved index call
|
|
- **Cursor for filter scanning**: cursor.reset overhead worse than inline byte loops
|
|
- **Direct strainer call**: YJIT already inlines context.invoke_single well
|
|
- **TruthyCondition subclass**: YJIT polymorphism at evaluate call site hurts more than 115 saved allocs
|
|
- **Index loop for filters**: YJIT optimizes each+destructure MUCH better than manual filter[0]/filter[1]
|
|
|
|
## Key Insights
|
|
|
|
- YJIT monomorphism > allocation reduction at this scale
|
|
- C-level StringScanner.scan/skip > Ruby-level byte loops (already applied)
|
|
- String#split is 2.5x faster than manual tokenization, but Liquid's grammar is too complex for regex
|
|
- 74% of total CPU time is GC — alloc reduction is the highest-leverage optimization
|
|
- But YJIT-deoptimization from polymorphism costs more than the GC savings
|
|
|
|
## Remaining Ideas
|
|
|
|
- **Tokenizer: use String#index + byteslice instead of StringScanner**: avoid the StringScanner overhead entirely for the simple case of finding {%/{{ delimiters
|
|
- **Pre-freeze all Condition operator lambdas**: reduce alloc in Condition initialization
|
|
- **Avoid `@blocks = []` in If with single-element optimization**: use `@block` ivar for single condition, only create array for elsif
|
|
- **Reduce ForloopDrop allocation**: reuse ForloopDrop objects across iterations or use a lighter-weight object
|
|
- **VariableLookup: single-segment optimization**: for "product.title" (1 lookup), use an ivar instead of 1-element Array
|
|
|