Slim VS. Haml: Performance Perspective
Background
Slim and Haml are two popular template language for Ruby on Rails, and there are many debates on which one is better all over the internet.
Luckily there are some benchmark tools on GitHub which may help to make a final decision.
I just pick up one from the official Slim GitHub repository: https://github.com/slim-template/slim
How-to Run Benchmark Test
Step 1: clone the code
$ git clone https://github.com/slim-template/slim
Step 2: install haml and slim for your rubies
$ gem install haml slim -N
On this post is written the slim version is 2.0.2 and haml version is 4.0.5.
Step 3: run the benchmark and review the generated report
$ cd benchmarks $ ruby run-benchmarks.rb 1000 Iterations Rehearsal --------------------------------------------------- (1) erb 0.040000 0.000000 0.040000 ( 0.035554) (1) erubis 0.030000 0.000000 0.030000 ( 0.034831) (1) fast erubis 0.030000 0.000000 0.030000 ( 0.028304) (1) temple erb 0.060000 0.000000 0.060000 ( 0.061399) (1) slim pretty 0.090000 0.000000 0.090000 ( 0.091697) (1) slim ugly 0.050000 0.000000 0.050000 ( 0.048000) (1) haml pretty 0.250000 0.000000 0.250000 ( 0.247935) (1) haml ugly 0.220000 0.000000 0.220000 ( 0.220167) (2) erb 0.090000 0.000000 0.090000 ( 0.093170) (2) erubis 0.070000 0.000000 0.070000 ( 0.065629) (2) temple erb 0.080000 0.000000 0.080000 ( 0.083807) (2) slim pretty 0.140000 0.000000 0.140000 ( 0.134829) (2) slim ugly 0.090000 0.000000 0.090000 ( 0.087713) (2) haml pretty 0.280000 0.000000 0.280000 ( 0.286019) (2) haml ugly 0.280000 0.000000 0.280000 ( 0.281315) ------------------------------------------ total: 1.800000sec user system total real (1) erb 0.030000 0.000000 0.030000 ( 0.031230) (1) erubis 0.030000 0.000000 0.030000 ( 0.027214) (1) fast erubis 0.020000 0.000000 0.020000 ( 0.019729) (1) temple erb 0.050000 0.000000 0.050000 ( 0.050958) (1) slim pretty 0.090000 0.000000 0.090000 ( 0.087899) (1) slim ugly 0.040000 0.000000 0.040000 ( 0.039730) (1) haml pretty 0.230000 0.000000 0.230000 ( 0.232516) (1) haml ugly 0.210000 0.000000 0.210000 ( 0.214131) (2) erb 0.070000 0.000000 0.070000 ( 0.079034) (2) erubis 0.050000 0.000000 0.050000 ( 0.052715) (2) temple erb 0.090000 0.000000 0.090000 ( 0.081411) (2) slim pretty 0.120000 0.000000 0.120000 ( 0.121075) (2) slim ugly 0.070000 0.000000 0.070000 ( 0.067838) (2) haml pretty 0.280000 0.000000 0.280000 ( 0.285198) (2) haml ugly 0.260000 0.000000 0.260000 ( 0.258908) (1) Compiled benchmark. Template is parsed before the benchmark and generated ruby code is compiled into a method. This is the fastest evaluation strategy because it benchmarks pure execution speed of the generated ruby code. (2) Compiled Tilt benchmark. Template is compiled with Tilt, which gives a more accurate result of the performance in production mode in frameworks like Sinatra, Ramaze and Camping. (Rails still uses its own template compilation.) (3) Parsing benchmark. Template is parsed every time. This is not the recommended way to use the template engine and Slim is not optimized for it. Activate this benchmark with 'rake bench slow=1'. Temple ERB is the ERB implementation using the Temple framework. It shows the overhead added by the Temple framework compared to ERB.
My Customized Benchmark Test
Default iteration is 1000, which makes the difference too small, so I update it to 100,000 in run-benchmarks.rb
Then I run 9 rounds of test under this configuration matrix:
Ruby 1.9.3 | Ruby 2.0.0 | Ruby 2.1.1 | |
Rails 3.2.17 | √ | √ | √ |
Rails 4.0.4 | √ | √ | √ |
Rails 4.1.0 | √ | √ | √ |
Compiled benchmark mode
Row Data
Ruby Version | Rails Version | erb | erubis | fast erubis | temple erb | slim pretty | slim ugly | haml pretty | haml ugly | slim ugly vs. erb |
1.9.3 | 3.2.17 | 4.33 | 3.65 | 3.65 | 6.62 | 9.13 | 5.16 | 26.64 | 24.99 | 19.17% |
4.0.4 | 4.31 | 3.63 | 3.7 | 6.2 | 9.07 | 5.15 | 26.39 | 24.85 | 19.49% | |
4.1.0 | 4.11 | 3.47 | 3.63 | 6.09 | 8.87 | 5.06 | 26.02 | 24.4 | 23.11% | |
2.0.0 | 3.2.17 | 3.81 | 3.32 | 3.17 | 6.2 | 9.55 | 4.78 | 25.19 | 22.41 | 25.46% |
4.0.4 | 3.83 | 3.35 | 3.39 | 6.01 | 9.4 | 4.87 | 25.16 | 22.29 | 27.15% | |
4.1.0 | 3.75 | 3.27 | 3.14 | 6.15 | 9.29 | 4.75 | 24.94 | 22.22 | 26.67% | |
2.1.1 | 3.2.17 | 3.12 | 2.74 | 2.81 | 5.21 | 8.41 | 4.31 | 22.31 | 20.29 | 38.14% |
4.0.4 | 3.15 | 2.75 | 2.77 | 5.24 | 8.51 | 4.33 | 21.72 | 19.9 | 37.46% | |
4.1.0 | 3.11 | 2.69 | 2.72 | 5.08 | 8.36 | 4.29 | 21.75 | 20.01 | 37.94% |
Ruby/Rails Perspective
Template Language Perspective
Conclusion
From Figure 1-1 it can be seen that:
- Ruby 2.1.1 is a little better than 1.9.3/2.0.0
- There is little difference for template languages between 1.9.3 and 2.0.0, except haml
- For haml 2.1.1 > 2.0.0 > 1.9.3
- If it is decided to use haml, then you can choose any version of Ruby and Rails.
From Figure 1-2:
- Haml is the worst
- Slim ugly is worse than erb, from between 19% to 38%.
- Comparing slim ugly to erb, Ruby 1.9.3 has the closest relative percentage , which is about 19% slower, while Ruby 2.1.1 the furthest, which is 38% slower
- Slim ugly performs best on 2.1.1 while worst on 1.9,3
- There is little difference for slim ugly on any version of Ruby/Rails
Compiled Tilt Benchmark Mode
Row Data
Ruby Version | Rails Version | erb | erubis | temple erb | slim pretty | slim ugly | haml pretty | haml ugly | slim ugly vs. erb |
1.9.3 | 3.2.17 | 8.61 | 6.35 | 9.41 | 12.49 | 8.07 | 28.56 | 25.61 | -6.27% |
4.0.4 | 8.62 | 6.29 | 9.67 | 12.79 | 8.35 | 28.36 | 25.78 | -3.13% | |
4.1.0 | 8.52 | 6.15 | 9.46 | 12.37 | 7.98 | 27.71 | 25.08 | -6.34% | |
2.0.0 | 3.2.17 | 8.57 | 6.14 | 9.33 | 12.97 | 7.95 | 29.51 | 27.55 | -7.23% |
4.0.4 | 8.53 | 6.15 | 9.23 | 13.06 | 7.76 | 29.81 | 27.44 | -9.03% | |
4.1.0 | 8.45 | 6.06 | 9.22 | 12.82 | 7.86 | 30.7 | 27.41 | -6.98% | |
2.1.1 | 3.2.17 | 6.54 | 4.96 | 7.13 | 10.51 | 6.19 | 22.2 | 20 | -5.35% |
4.0.4 | 6.5 | 4.91 | 6.95 | 10.42 | 6.15 | 21.36 | 19.54 | -5.38% | |
4.1.0 | 6.48 | 4.9 | 6.94 | 10.36 | 6.15 | 21.31 | 19.39 | -5.09% |
Ruby/Rails Perspective
Template Language Perspective
Conclusion
From Figure 1-3 it can be concluded that:
- Ruby 2.1.1 is a little better thatn 1.9.3/2.0.0,
- There is little difference for template languages between 1.9.3 and 2.0.0, except haml
- For haml 2.1.1 > 2.0.0 > 1.9.3
- If it is decided to choose haml, then Ruby 2.1. is recommended
From Figure 1-4:
- Haml is the worst
- Slim ugly is a little better than erb, from between 3% to 9%
- Comparing slim ugly to erb, Ruby 1.9.3 has the best relative percentage , which is about 8% faster
- Slim ugly on Ruby 2.1.1 runs the fastest
- There is no difference for slim ugly on any version of Rails; meanwhile, Ruby 2.1.1 > 2.0.0 > 1.9.3
Final Conclusion
Slim ugly indeed is much faster than haml, while slightly slower than erb.
Considering coding efficiency and run-time efficiency, maybe slim is the best choice.
Further Benchmark Update
Perhaps I can try different template data, for example, change the structure of view.erb/view.haml/view.slim, to experience more.
Nice post and very detailed writeup. Thank you for staying factual and un-opinionated in this comparison. It’s easy to dip into finger pointy mode with such comparisons so I commend you for not doing so.
I do want to point out that extrapolating your results, haml will add .00025ms (or 0.25ns) of overhead to each page request you serve. Unless you render your page 1000 times per request in which case you add .25ms per request. Not much to worry about unless you’re doing a few 100k requests per second. #amirite?
But I really do appreciate this blog post. We were having a discussion at work about haml’s poor performance and I was recently introduced to slim. So far, I’m not a fan of the syntax compared to haml. I am however interested to dig more into the implementation of each to discover exactly how they get slim to be an order of magnitude more efficient.
Cheers.
As my teacher would say: “what unit is it? puppies?”. tl;dr, so the graphs were useless to me becuase I couldn’t see if 1/s or milliseconds per request or what…
+1
+1
The units were seconds per 100,000 template renders, from what I can see.
would be nice if you had added builder to your benchmark.
it’s pure ruby with Builder::XmlMarkup tool. it always been with rails, since the beginning. it used to have the .rxml extension.
See also: https://github.com/rails/rails/issues/17565
I can do a render inside of my haml and slim code.
Here is my code:
doctype html
html
head
title Slim Examples
javascript:
alert(‘Slim supports embedded javascript!’)
body
h1 Markup examples
#content
p This example shows you how a basic Slim file looks.
div id=”footer”
== render :partial => ‘footer’
and this is the error:
slim pretty(eval):113:in `run_slim_pretty’: undefined method `render’ for # (NoMethodError) from run-benchmarks.rb:49:in `block in init_compiled_benches’.
Any help?
Reblogged this on Diary of an ADHD fellow and commented:
Interesting & solid 🙂