liquid.cr icon indicating copy to clipboard operation
liquid.cr copied to clipboard

Why is it astonishingly slow?

Open romul opened this issue 6 years ago • 3 comments

I've benchmarked this project versus Shopify/liquid on Ruby 2.5 And got very strange results:

Ruby

tpl = Liquid::Template.parse(template)
ctx = Liquid::Context.new
ctx["order"] = order

Benchmark.ips do |x|
  x.report("parse & render") {
    ctx = Liquid::Context.new
    ctx["order"] = order
    Liquid::Template.parse(template).render(ctx)
  }
  x.report("render") {
    tpl.render(ctx) 
  }
end

Crystal

tpl = Liquid::Template.parse(template)
ctx = Liquid::Context.new
ctx.set("order", order)

Benchmark.ips do |x|
  x.report("parse & render") {
    ctx = Liquid::Context.new
    ctx.set("order", order)
    Liquid::Template.parse(template).render(ctx)
  }
  x.report("render") { tpl.render(ctx) }
end

Ruby (template without filters)

      parse & render      2.698k (± 3.8%) i/s -     13.585k in   5.042274s
              render     10.020k (± 2.6%) i/s -     50.085k in   5.002127s

Crystal (template without filters)

      parse & render   1.56k (639.72µs) (± 2.02%)   171kB/op   2.52× slower
              render   3.94k (253.49µs) (± 1.97%)  73.9kB/op        fastest

Ruby (template with one strip_newlines filter)

      parse & render      2.547k (± 3.3%) i/s -     12.760k in   5.014887s
              render      8.649k (± 4.6%) i/s -     43.962k in   5.094069s

Crystal (template with one strip_newlines filter)

      parse & render   1.50k (667.40µs) (± 1.20%)  179kB/op        fastest
              render   1.29k (776.84µs) (±57.11%)  235kB/op   1.16× slower

Crystal version was built with --release flag, but it didn't help. As you can see, Liquid on Crystal renders in 2.5 slower than on Ruby in the best case (without any filters). Using Liquid-filters kills performance of rendering on Crystal completely. And surprisingly just render starts to take more time than parse + render.

P.S. Here is the test data

romul avatar Sep 05 '19 13:09 romul

The issue seems to be in the for loop.

 render w/o for   22.06k ( 45.32µs) (±10.62%)   5.9kB/op        fastest
render with for   2.34k (428.26µs) (± 9.74%)  68.3kB/op   9.45× slower

TechMagister avatar Sep 06 '19 18:09 TechMagister

@TechMagister Well, now we know that using for & filters in a template kills rendering performance... But they both are essential parts of Liquid. Why can't we port code from ruby version instead of reinventing a slow wheel?

romul avatar Sep 10 '19 15:09 romul

@romul We can port code, but I have no time for this for the moment :/

TechMagister avatar Sep 12 '19 14:09 TechMagister