Rails from
“good” to fast
How to get the view rendering
from ~600ms to ~60ms
Slide 2
Slide 2 text
What’s the slowest
part in Rails?
• Request Handling (ActionDispatch)
• NO!
• Database Queries (ActiveRecord)
• NO, just a bit!
• Rendering (ActionView, HAML, JBuilder)
• YES!
Slide 3
Slide 3 text
Let’s build a Blog
github.com/timoschilling/YetAnotherBlog
Why ~5ms?
Slide 4
Slide 4 text
Asset Overhead
Prod
Dev
1 Asset
Dev
100 Assets
Slide 5
Slide 5 text
Fix Asset Overhead
How?
Dev
1 Asset
Dev
100 Assets
Slide 6
Slide 6 text
Even Faster?
Slide 7
Slide 7 text
The Code
Slide 8
Slide 8 text
Render a Index with
100 Items
Slide 9
Slide 9 text
Side Note:
Every Query is a lie!
0.3ms + 0.4ms + 4.4ms +0.6ms = 5.7ms
5.7ms != 6.1ms
Slide 10
Slide 10 text
No content
Slide 11
Slide 11 text
Why 5.7ms != 6.1ms?
ActiveRecord show only the query time!
Not the real amount of each operation!
Slide 12
Slide 12 text
How to get a real value?
Before:
(0.3ms) SELECT COUNT(*)…
Post Load (0.4ms) …
User Load (0.4ms) …
Comment Load (4.4ms) …
User Load (0.6ms) …
Completed in 568ms
(Views: 561.9ms |
ActiveRecord: 6.1ms)
After:
(0.3ms) SELECT COUNT(*)…
Post Load (0.4ms) …
User Load (0.4ms) …
Comment Load (4.4ms) …
User Load (0.6ms) …
DB Queries: 78.85ms
Completed in 568ms
(Views: 489,1ms |
ActiveRecord: 6.1ms)
Slide 13
Slide 13 text
Hint!
If you use Trailblazer:
You will get this kind of measurement
for free, in the future.
Slide 14
Slide 14 text
How to make it
faster?
Cache!?
Slide 15
Slide 15 text
Russian Doll Caching
from
570ms
to
677ms
???
Slide 16
Slide 16 text
Russian Doll Caching
It helps only if you have slow views!
This view has the same render time as a view
without `sleep` with Russian Doll Caching
Slide 17
Slide 17 text
good old
Rails.cache.fetch
It’s fast!
But now I need to manage the cache!
:(
85ms
Slide 18
Slide 18 text
tl;dr
Rails caching sucks!
Slide 19
Slide 19 text
Again:
How to make it faster?
Don’t use ActionView!
But how?
Use Cells!
Slide 20
Slide 20 text
Cells?
A gem for ViewModel’s,
written by this awesome guy:
Slide 21
Slide 21 text
Demo
Slide 22
Slide 22 text
Status:
~650ms -> ~150ms
Slide 23
Slide 23 text
Where is the Time?
• 150ms Request
• DB: 70ms
• ActiveRecord: 6.1ms
• ActionView: 78.1ms
• Cells: 71.4ms
Slide 24
Slide 24 text
Next Step:
remove index (action)view
(demo)
Slide 25
Slide 25 text
Where is the Time?
• 145ms Request
• DB: 70ms
• ActiveRecord: 6.1ms
• ActionView: 74.1ms
• Cells: 71.4ms
Slide 26
Slide 26 text
Next Step:
remove layout (action)view
(demo)
Slide 27
Slide 27 text
Where is the Time?
• 145ms Request
• DB: 70ms
• ActiveRecord: 6.1ms
• Cells: 71.4ms
Slide 28
Slide 28 text
How does tempting
works?
Slide 29
Slide 29 text
Why need that ~70ms?
• 1 Layout
• Index List
• 100 Post
• + 1 User
• + 1 Comment
• + 1 User
• = 404 Renderings
• 404 Renderings
• each rendering
needs 100 method
call (theoretical
assumption)
Slide 30
Slide 30 text
70ms vs. 4ms
Where the time goes by?
Tilt!
Slide 31
Slide 31 text
What does Tilt do?
• one time
• compile the template
• build a method
• cache this method
• per rendering
• bind the method to the context
• call the method
• unbind the method from context
• one time
• compile the template
• build a method
• cache this method
• per rendering
• bind the method to the context
• call the method
• unbind the method from context
Slide 32
Slide 32 text
Solution:
Hand build tilt replacement
Slide 33
Slide 33 text
Where is the Time?
• 91ms Request
• DB: 70ms
• ActiveRecord: 6.1ms
• Cells: 17.4ms
Slide 34
Slide 34 text
ActiveSupport::Notifications
• Nice
• But slow
• One event costs ~0.05ms
Slide 35
Slide 35 text
Path helpers
• post_path(model) # => f***ing slow
• post_path(id: model.id) # => slow
• “/posts/#{id}” # => fast
• brings up to 4ms (50%)
Slide 36
Slide 36 text
Cell::Mailer
Slide 37
Slide 37 text
Real World App
Slide 38
Slide 38 text
Jbuilder
Slide 39
Slide 39 text
Faster? How?
A gem JSON/XML Object Mapper,
written by this awesome guy:
Representable
Slide 40
Slide 40 text
Representable
Slide 41
Slide 41 text
Jbuilder
vs.
Representable
from ~230ms to ~80ms
Slide 42
Slide 42 text
Form’s
SimpleForm
Slide 43
Slide 43 text
Faster? How?
A form builder gem,
written by this awesome guy:
Formular