doy / text-handlebars

http://handlebarsjs.com/ for Text::Xslate
http://metacpan.org/release/Text-Handlebars
6 stars 9 forks source link

"if" block bodies not pre-compiled. Large performance hit. #7

Open veep opened 8 years ago

veep commented 8 years ago

The bodies of "if" blocks don't seem to be pre-compiled. This results in much slower template rendering.

For the script attached, render_string is 559/second TT, 52/second HBS. But render, using caching, is 202390 for TT, 76 HBS. We saw comparable performance differences with real-world templates as well. (the on-disk row.tt and row.hbs have the some content as the strings in the script). hb-test.txt

amit777 commented 7 years ago

@veep did you end up using something else? I was just about to start using this module but noticed your perf test. I ran them on my own system and got the following results:

render: HBS count 258 TT count 529329
render_string: HBS count 167 TT count 1679
amit777 commented 7 years ago

does this commit look like it may address the perf issue you identified? https://github.com/arodland/text-handlebars/commit/305f52bf1a466b81fe59d0ac5be4b104c152a373

amit777 commented 7 years ago

as a quick FYI, I applied the caching update that was coded in that fork, and here is the updated performance metrics:

render is 150x faster render_string is 3x faster

render: HBS count 39098 TT count 557055
render_string: HBS count 419 TT count 1679
amit777 commented 7 years ago

as comparison, handlebars in nodejs metrics:

hbs not precompiled x 2,430 ops/sec ±3.30% (83 runs sampled)
hbs precompiled x 938,557 ops/sec ±1.32% (84 runs sampled)
aaminoff commented 4 years ago

I believe I am running in to this problem as well. I have a {{#if}} inside a {{#each}} (actually my own helpers written in perl that work similarly). Looking at it in NYTProf, it looks like a lot of time is spent compiling templates. My hypothesis is that if I loop over 100 items, the same piece of template is re-compiled 100 times. Does that seem right?

The patch posted above by amit777 seems like a reasonable solution, but A) am I right in assuming that this is a problem that would be common to all Text::Xslate subclasses? and B) would a better solution be to find the pre-compiled piece of the template that was originally compiled by load_file and use that, instead of re-compiling and then cacheing it?

amit777 commented 4 years ago

@aaminoff I would love to know what you come up with in the end.

aaminoff commented 4 years ago

I ended up using that patch and actually it works pretty effectively. If you use a cache directory the template pieces inside the {{#if}} are compiled and actually saved to disk under a HASH subdirectory. I re-profiled and all the time spent re-compiling disappeared. In theory, it should be possible to compile the templates when you read the file and use them, but this solution works. I guess it would be helpful if that patch could get pulled into this repo.