58 Commits

Author SHA1 Message Date
Tobi Lutke
c5a44be104
perf: optimize compiled template allocations and performance
Major optimizations to reduce allocations and improve execution speed:

1. For loops: Replace catch/throw with while + break flag
   - Uses while loop with index instead of .each with catch/throw
   - Break implemented with flag variable, continue with next
   - Result: 18% fewer allocations, 85% faster for simple loops

2. Forloop property inlining
   - Inline forloop.index as (__idx__ + 1), forloop.first as (__idx__ == 0), etc.
   - Completely eliminates forloop hash allocation when all properties inlinable
   - Result: Loop with forloop went from +46% MORE to -16% FEWER allocations

3. LR.to_array helper with EMPTY_ARRAY constant
   - Centralized array conversion with frozen empty array for nil
   - Avoids allocations for empty collections

4. Inline LR.truthy? calls
   - Replace LR.truthy?(x) with (x != nil && x != false)
   - Eliminates method call overhead in conditions

5. Keep Time methods available in sandbox for date filter

Overall results:
- Allocations: 3.5% MORE -> 24% FEWER (27% improvement)
- Time: 64% faster -> 89% faster (25% improvement)

Also adds:
- compile_profiler.rb for measuring allocations/performance
- compile_acceptance_test.rb for output equivalence testing
- OPTIMIZATION.md documenting optimization status
2025-12-31 13:24:33 -04:00
Claude
5cdbce7d6e
Improve benchmark output clarity
Add explicit summary showing pre-compiled is X times FASTER,
and explain that "X slower" in comparison means relative to
the fastest option (pre-compiled Ruby). Higher i/s = faster.
2025-12-31 15:25:54 +00:00
Claude
7be2922f91
Fix compiler output equivalence and add comprehensive tests
- Fix forloop.first/last/size lookups to try hash key before method call
- Fix tablerow cols parameter to use attributes['cols'] not @cols
- Fix tablerow output format to match interpreter (newlines, row boundaries)
- Fix capture compiler to access @body directly instead of iterating nodelist
- Add CompiledTemplate class to encapsulate code and external_tags
- Add external filter support via filter_handler
- Add debug mode warnings for external tag/filter calls
- Add Ruby 3.3 compatibility shim for peek_byte/scan_byte
- Add comprehensive unit tests for output equivalence
- Add benchmark comparing compiled vs interpreted rendering

All 30 test templates now produce identical output between compiled
Ruby and interpreted Liquid. Pre-compiled Ruby is 1.68x faster.
2025-12-31 14:58:06 +00:00
Michael Go
97cada61f9 remove Expression2 strscan workaround 2025-01-10 14:23:57 -04:00
Michael Go
7c592c1c00 store StringScanner in ParseContext and reuse it through parsing 2025-01-07 14:32:45 -04:00
Michael Go
8ecb703d4d use StringScanner to improve Expression Parsing and Tokenizer 2025-01-07 14:32:06 -04:00
Michael Go
c77ff68573 clean up all warnings by using new Environment 2024-11-04 16:15:05 -04:00
Ian Ker-Seymer
b3553787c8
Speed up the lexer for Ruby 3.4+ (#1832)
* Speed up lexing

* Bump msrv to 3.0 (from 2.7)

* Normalize test for ruby-head compat

* Fix bug when parsing negative numbers
2024-10-23 14:15:33 -04:00
Guilherme Carreiro
9ab688eada
Update rubocop-shopify (2.7.0 -> 2.12.0) (#1687) 2023-02-15 08:40:59 +01:00
Guilherme Carreiro
84a0289ebc
Fix CI (as it installs RuboCop 1.45.1 and fails) (#1686) 2023-02-14 12:24:38 +01:00
Ghouse Mohamed
6c187b8470 Fix typo: syntetic -> synthetic 2022-03-27 23:18:01 +05:30
Peter Zhu
996bfe0c82 Fix benchmark for breaking change in Psych 4
Psych 4 introduces a breaking change (ruby/psych#487) where
`Psych#load`/`Psych#load_file` now default to safe loading,
meaning that YAML references are not allowed anymore. This
commit changes the benchmark to use `Psych#unsafe_load_file`
when it's available.
2021-06-10 13:01:16 -04:00
Peter Zhu
e71e53ffb5 Refactor render_layout method for serialization 2021-01-11 14:00:39 -05:00
Dylan Thacker-Smith
67eca3f58d Upgrade rubocop and style guide for ruby 2.7 compatibility 2020-01-09 13:15:34 -05:00
Alessandro Diogo Brückheimer
e83b1e4159 Add ForceEqualSignAlignment to .rubocop.yml (#1190)
* Add ForceEqualSignAlignment to .rubocop.yml

* Revert ForceEqualSignAlignment cop

* Update method alignment

* Undo addition of whitespace to improve readability

* Fix missing alignment
2019-10-21 21:18:48 +10:00
Mike Angell
5302f40342
Rubocop fixes (#1182) 2019-10-07 17:06:47 +11:00
Mike Angell
b667bcb48b
Shopify stye guide fixes (#1160) 2019-09-20 02:08:11 +10:00
Mike Angell
0d26f05bb8
Enabled frozen string literals (#1154)
* Enabled frozen string literals

* Update rubocop config

* Prefer string interpolation in simple cases

Co-Authored-By: Dylan Thacker-Smith <dylan.smith@shopify.com>
2019-09-18 13:19:45 +10:00
Mike Angell
799da202df Apply simple rubocop fixes 2019-08-31 21:58:33 +10:00
Mike Angell
8f68cffdf1 Resolve failing rubocop issues 2019-08-29 00:45:38 +10:00
Tobias Lütke
0ce8aef229
Merge pull request #1103 from ashmaroli/ci-profile-memory
Add a CI job to profile memory usage of commit
2019-08-27 15:11:55 -04:00
Ashwin Maroli
ab698191b9 Add a CI job to profile memory usage of commit 2019-05-17 22:47:05 +05:30
Florian Weingarten
9640e77805 render_to_output_buffer 2019-04-23 17:06:29 -04:00
Florian Weingarten
2a1ca3152d liquid without the garbage 2019-04-22 16:34:31 -04:00
Florian Weingarten
c67b77709d rake memory_profile:run 2019-04-17 19:09:26 +01:00
Jerry Liu
a93eac0268 Introduce new benchmarking methods to liquid to use on rubybench 2017-01-27 10:56:16 -05:00
Florian Weingarten
82269e2509 fix a few more rubocop offenses 2015-06-04 13:09:58 -04:00
Florian Weingarten
3372ca8136 Rubocop 2015-05-14 14:37:18 +00:00
Jean Boussier
b31df0fb3d Mordernize code base with __dir__ and require_relative 2015-05-13 15:33:00 -04:00
James Reid-Smith
4592afcc8b Updated History.md and removed a couple remaining methods using the old signature 2015-04-27 15:45:44 +00:00
Justin Li
4e870302b1 Add env var for saving stackprof graphviz output 2014-11-04 18:38:14 +00:00
Dylan Thacker-Smith
0573b63b4c Use super rather than render_all in single block render classes. 2014-09-12 16:58:07 -04:00
Florian Weingarten
a74d40f1e5 benchmark/ips 2014-08-11 19:22:06 +00:00
Jason Hiltz-Laforge
32349033a9 Add object profiling in addition to cpu profiling 2014-07-16 15:32:04 +00:00
Dylan Thacker-Smith
f5502e8152 Remove active_support from the development dependancies. 2014-04-11 14:26:40 -04:00
Dylan Thacker-Smith
d1bfda15e3 Add profile:strict rake task. 2014-03-21 21:54:53 -04:00
Dylan Thacker-Smith
d4ecaff8b8 Refactor to create tags with a parse class method instead of new.
By moving parse out of the initializer, we can call super at the start of
the initializers for subclasses, and avoid the nasty allocate hack.
2014-03-20 16:10:10 -04:00
Dylan Thacker-Smith
4b69f6ae83 Use render! in benchmarks to avoid making it faster by breaking things. 2014-03-19 18:01:33 -04:00
Dylan Thacker-Smith
ff5c1f83f7 Merge pull request #318 from Shopify/stackprof
Use stackprof for profiling.
2014-03-14 10:27:46 -04:00
Dylan Thacker-Smith
f373b1003d Use stackprof for profiling. 2014-03-14 10:03:50 -04:00
Dylan Thacker-Smith
503d924274 Use start and end of string rather than line matching in regexes. 2014-03-13 17:56:42 -04:00
Tristan Hume
3b3961be39 Use lax mode by default so nothing breaks 2013-07-29 16:28:20 -04:00
Harry Brundage
bacacf2fd0 Remove the Token class from the lexer in favour of less smart but faster arrays 2013-07-26 15:14:01 -04:00
Tristan Hume
87b8ee7341 Add error mode switching 2013-07-26 11:45:13 -04:00
Tristan Hume
17d818b453 Fix profiler 2013-07-25 15:04:04 -04:00
Tristan Hume
0453d7e299 Fix benchmarks to use only valid liquid. 2013-07-25 11:51:51 -04:00
Florian Weingarten
0f5441b09e Convert legacy tab indentation to spaces and remove trailing whitespace from all lines 2013-06-26 19:53:09 -04:00
Tom Burns
b8fbd2b4fa typo 2013-05-16 20:25:31 -04:00
Tom Burns
2af4ea1295 Support benchmarking templates with 'include' tag 2013-05-12 22:17:08 -04:00
Tobias Lütke
05d9976e16 fix benchmark 2012-10-29 16:47:57 -04:00