A Rails 7.1 app that uses RSX — JSX-style templates in Ruby — to render a catalog of Ruby on Rails courses. The same catalog is also implemented in isolated html.erb views so the two stacks can be compared side by side.
The Gemfile pins rsx-rb to 0.1.0.
Ruby 3.3.0.
bin/setup
bin/devbin/dev starts Puma and the Tailwind watcher. Then open http://127.0.0.1:3000.
Two isolated stacks. They share no views, components, or controllers.
| RSX | ERB | |
|---|---|---|
| Home | / |
/erb |
| Course table | /courses |
/erb/courses |
| Course detail | /courses/:id |
/erb/courses/:id |
Example detail page: /courses/learn-ruby-on-rails-full-course vs /erb/courses/learn-ruby-on-rails-full-course.
| RSX | ERB | |
|---|---|---|
| Controllers | app/controllers/ |
app/controllers/erb/ |
| Views | app/views/pages, app/views/courses (*.html.rsx) |
app/views/erb/pages, app/views/erb/courses (*.html.erb) |
| Components | app/components/*.rsx |
app/views/erb/components/_*.html.erb |
| Layout | app/views/layouts/application.html.erb |
app/views/erb/layouts/_document.html.erb |
| Helpers | — | app/helpers/erb/ |
Both controllers pass the same hardcoded course list (name, hours, YouTube URL, channel, thumbnail) into a nested table: catalog → table → row → thumbnail / meta / duration / watch.
bin/rails testThat runs:
- Functional coverage for the RSX pages (
/,/courses,/courses/:id) - Functional coverage for the ERB pages (
/erb,/erb/courses,/erb/courses/:id) - A performance suite that prints an RSX vs ERB comparison to the terminal
Sample size defaults to 60 timed iterations after 8 warmups. Override if you want a longer or shorter run:
PERF_ITERATIONS=120 PERF_WARMUP=15 bin/rails testRatio is ERB / RSX. Below 1.00 means ERB was faster; above 1.00 means RSX was faster. Allocs are Ruby objects per call. The missing-course path is dominated by Rails exception handling, not the template engine, so it is excluded from the “Rendering + requests” line.
Numbers will move with hardware, Ruby, and PERF_ITERATIONS. Re-run bin/rails test for a fresh table.
==============================================================================
RSX vs ERB performance comparison
Iterations: 60 timed (8 warmup) | times are per-call averages
==============================================================================
Scenario RSX ms ERB ms Ratio Winner
------------------------------------------------------------------------------
GET home 2.134 3.941 1.85x RSX
GET courses index 1.961 4.832 2.46x RSX
GET course show 1.852 3.651 1.97x RSX
GET missing course 239.970 251.033 1.05x tie
render course table 0.590 2.386 4.04x RSX
render course row 0.383 0.458 1.20x RSX
render course detail 0.528 1.637 3.10x RSX
render empty table 0.317 0.163 0.52x ERB
render duration badges 0.348 0.662 1.91x RSX
------------------------------------------------------------------------------
Rendering + requests 8.113 17.731 2.19x
Allocs / call 10369 17785 1.72x
All scenarios 248.082 268.764 1.08x
Ratio is ERB / RSX. Below 1.00 means ERB was faster; above 1.00 means RSX was faster.
Allocs are Ruby objects per call. Override with PERF_ITERATIONS and PERF_WARMUP.
==============================================================================
On this machine, RSX 0.1.0 was faster on the real page and component renders (about 2.19× on the rendering + request total, and 1.72× fewer allocations).
==============================================================================
RSX vs ERB performance comparison
Iterations: 60 timed (8 warmup) | times are per-call averages
==============================================================================
Scenario RSX ms ERB ms Ratio Winner
------------------------------------------------------------------------------
GET home 1.900 3.775 1.99x RSX
GET courses index 1.886 4.602 2.44x RSX
GET course show 1.940 3.444 1.77x RSX
GET missing course 241.206 246.333 1.02x tie
render course table 0.610 2.630 4.31x RSX
render course row 0.395 0.502 1.27x RSX
render course detail 0.538 1.591 2.96x RSX
render empty table 0.311 0.162 0.52x ERB
render duration badges 0.335 0.631 1.88x RSX
------------------------------------------------------------------------------
Rendering + requests 7.915 17.336 2.19x
Allocs / call 10479 17785 1.70x
All scenarios 249.121 263.669 1.06x
Ratio is ERB / RSX. Below 1.00 means ERB was faster; above 1.00 means RSX was faster.
Allocs are Ruby objects per call. Override with PERF_ITERATIONS and PERF_WARMUP.
==============================================================================
0.2.1 keeps the same 2.19× rendering + request advantage vs ERB, with slightly lower RSX wall time on that total (7.915 ms vs 8.113 ms in 0.1.0). Allocations are about 1.70× fewer than ERB.
