Let's look at Fortitude’s performance.
This is the time (in milliseconds) required to render a highly realistic, complex Rails view page, creating a total of about 380 KBytes of HTML. (This is a rather large page; by comparison, the entire front page of nytimes.com is, as of this writing, about 270KBytes.)
| Engine | Time (ms) | vs. ERb | Garbage (objects) | vs. ERb |
|---|---|---|---|---|
| ERb | 31.7 | 100% | 41,000 | 100% |
| Slim | 30.0 | 95% | 31,000 | 76% |
| HAML | 95.1 | 300% | 191,000 | 467% |
| Erector | 649.1 | 2,048% | 241,000 | 588% |
| Fortitude | 18.1 | 57% | 22,000 | 55% |
Fortitude is nearly twice as fast as ERb, and almost five times as fast as HAML. Fortitude is over half again as fast as Slim.
Further, Fortitude is the fastest general-purpose Rails templating engine available. (By general-purpose, we mean an engine that can include arbitrary logic in views. So-called logicless templating engines move a significant amount of the logic required to render views out of the view file itself, and thus do not consist of a true “apples-to-apples” comparison.)
Fortitude also generates only about half as much garbage as ERb, and less than one-eighth as much as HAML. Though often overlooked, every object created as garbage requires time to collect, and this is also a non-trivial contribution to most applications’ performance.
These results are for a large, complex benchmark, intended to accurately assess a templating engine's performance on a real-world Rails application. Next, let’s look at some microbenchmarks that measure various abstraction penalties — how much slower templating engines get when you use the features they provide to structure your view code better.
| Local Variable Passing | ||||
|---|---|---|---|---|
| Engine | Time (ms) | vs. ERb | Garbage (objects) | vs. ERb |
| ERb | 250 | 100% | 500,000 | 100% |
| HAML | 257 | 103% | 601,000 | 120% |
| Slim | 93 | 37% | 200,000 | 40% |
| Erector | 306 | 122% | 864,000 | 173% |
| Fortitude | 71 | 28% | 100,000 | 20% |
| Partial Calls | ||||
| Engine | Time (ms) | vs. ERb | Garbage (objects) | vs. ERb |
| ERb | 287 | 100% | 350,000 | 100% |
| HAML | 338 | 118% | 505,000 | 144% |
| Slim | 350 | 122% | 331,000 | 95% |
| Erector | 52 | 18% | 100,000 | 29% |
| Fortitude | 23 | 8% | 37,000 | 11% |
| HTML Escaping | ||||
| Engine | Time (ms) | vs. ERb | Garbage (objects) | vs. ERb |
| ERb | 57 | 100% | 121,000 | 100% |
| HAML | 50 | 88% | 131,000 | 109% |
| Slim | 34 | 60% | 90,000 | 74% |
| Erector | 55 | 96% | 152,000 | 125% |
| Fortitude | 5 | 9% | 10,000 | 8% |
| Translation Helper | ||||
| Engine | Time (ms) | vs. ERb | Garbage (objects) | vs. ERb |
| ERb | 223 | 100% | 350,000 | 100% |
| HAML | 191 | 86% | 310,000 | 89% |
| Slim | 201 | 90% | 310,000 | 89% |
| Erector | 256 | 115% | 410,000 | 117% |
| Fortitude | 156 | 70% | 280,000 | 80% |
These are microbenchmarks, designed to carefully measure only one aspect of a templating engine’s performance. While they aren’t necessarily reflective of a templating engine’s overall performance on real-world code, they can be very useful in helping you understand what kinds of things are fast, and what kinds of things are slow, on a particular templating engine.
Briefly, these microbenchmarks measure:
@global variables) is key to encapsulating code properly, which leads to reliability and maintainability.
#t helper, which is used extensively in any internationalized Rails application. For such applications, its speed is key. (Note that the #t helperis actually fairly slow itself, compared to the speed of view code; this causes differences among rendering engines to seem smaller on this test than they are on the other view microbenchmarks.)
As you can see from Fortitude’s results, not only is it a very-high-performance templating engine across the board, but it’s particularly strong in areas of abstraction — the very features, like breaking views into partials and passing local variables, that allow you to best build very well-factored view code. Compared to ERb, it’s over ten times as fast at invoking a partial, and generates almost a tenth as much garbage. Over a large application’s codebase, this can make a very significant difference in how fast your users see pages rendered to them — which is what really matters.
All of the benchmarks above are brand-new — they were developed in conjunction with Fortitude. (They are, of course, all available as open source in the rails_view_benchmarks GitHub repository.)
Why develop a new benchmark suite? When we started development of Fortitude, the goal was to use an existing set of benchmarks for views — after all, using something the community was familiar with is generally better.
However, it immediately became apparent that all of the existing benchmarks for Ruby or Rails templating engines were so small as to be unrealistic. They typically rendered very small amounts of HTML, in a single view, while interpolating minimal user data. Now, if your application consists entirely of single-file views with very small amounts of HTML and minimal user data, those are accurate benchmarks — but, then, if that’s the kind of application you have, view performance probably is pretty irrelevant to you in the first place.
Instead, we developed rails_view_benchmarks, with particular attention given to the real-world benchmark called place_page whose results are listed at the top of this page.
How different is this from previous view benchmarks? How real-world is it? We’ll once again let the numbers tell the tale:
| Slim Benchmark | Crowd Interactive Comparison | Steve Iannopollo’s Benchmark | Place Page | |
|---|---|---|---|---|
| View Files | 1 | 1 | 1 | 34 |
| Lines of Code | 23 | 7 | 55 | 915 |
| Bytes of HTML Generated | < 300 | < 300 | 2,600 | 380,000 |
In fact, this place_page benchmark is reverse-engineered from a real-world, large-scale Rails application (that renders that same view hundreds of thousands of times a day), and it‘s by far the largest and most realistic view benchmark available for Ruby or Rails now. It reflects the performance of a non-trivial, real application much, much better than any previous benchmark.
It’s completely fair to ask: does this stuff matter? And, of course, the answer is: it depends.
If you have an application that uniformly renders simple views with very little HTML in them, then, no, view performance probably doesn’t matter a great deal to you — and neither does all of the wonderful factoring of view code that you can do with Fortitude. You certainly can still use it and may enjoy it, but its real advantages aren’t nearly so big in such a situation. On the other hand, applications that are this way and stay this way, even if they’re successful, are pretty rare, outside of API clients rendering JSON and other such microservices.
If, on the other hand, you have an application with significant amounts of view code in it, or one that renders any non-trivial amount of HTML to the user, then, yes, view performance absolutely matters. It’s a cost that users have to pay on every single page they view, no matter what. And the choice of templating engine in particular is important because:
In the end, performance of a templating engine is one of those mundane things you never really think much about until you’re running at serious scale — and suddenly this tax that you pay on every single page hit starts to be significant. With Fortitude, you don’t have to worry: it’s the single fastest choice you can make for any Ruby or Rails application’s view layer.
You should choose Fortitude for its incredibly powerful code-factoring tools — but it’s good to know that it’s also extraordinarily fast, too.