rails html fragment caching with cache rocket
DESCRIPTION
Key-based fragment caching in Rails is a great way to improve server-side response times. The cache_rocket gem provides a few simple techniques to make html rendering even faster and more efficient. Discussed: usage, performance, and trade-offs of key-based caching techniques.TRANSCRIPT
![Page 1: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/1.jpg)
and����������� ������������������ lovekey-based����������� ������������������ HTML����������� ������������������ fragment����������� ������������������ caching
How����������� ������������������ I����������� ������������������ learnedto����������� ������������������ stop����������� ������������������ worrying
![Page 2: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/2.jpg)
TEE PARHAM@teeparham
![Page 3: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/3.jpg)
![Page 4: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/4.jpg)
![Page 5: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/5.jpg)
Do����������� ������������������ not����������� ������������������ expire����������� ������������������ keys
1
![Page 6: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/6.jpg)
Model����������� ������������������ associationsgovernexpiry
2
![Page 7: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/7.jpg)
3 Nestedcachingis����������� ������������������ best
![Page 8: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/8.jpg)
class Project has_many :todo_lists
class TodoList belongs_to :project, touch: true has_many :todos
class Todo belongs_to :todo_list, touch: true
![Page 9: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/9.jpg)
> todo = Todo.first => #<Todo id: 1, updated_at: "2013-11-19 00:24:01"> > todo.cache_key => "todos/1-20131119002401851149000"
cache_key
![Page 10: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/10.jpg)
> todo = Todo.first => #<Todo id: 1, updated_at: "2013-11-19 00:24:01"> > todo.cache_key => "todos/1-20131119002401851149000"
cache_key
![Page 11: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/11.jpg)
Project
Todo
TodoList
![Page 12: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/12.jpg)
> todo.cache_key=> "todos/1-20131119002401851149000"
> cache(‘todo_item’, todo)=> "todo_item/todos/1-20131119002401851149000"
view����������� ������������������ keys
![Page 13: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/13.jpg)
- @projects.each do |project| - cache [‘project’, project] do ...project... - project.todo_lists.each do |todo_list| - cache [‘todo_list’, todo_list] do ...todo_list... - todo_list.todos.each do |todo| - cache [‘todo’, todo] do ...todo...
![Page 14: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/14.jpg)
YO����������� ������������������ DAWG
![Page 15: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/15.jpg)
has_many����������� ������������������ ����������� ������������������ :arrows
![Page 16: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/16.jpg)
adifferenthammer
![Page 17: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/17.jpg)
User*
City
User
Idea**
![Page 18: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/18.jpg)
YO����������� ������������������ DAWG?*
![Page 19: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/19.jpg)
.stream-item .item-rail .avatar-stream = avatar(idea.user) .mobile-meta.show-for-small Suggested by #{user_link(idea.user)} %br/ = l idea.created_at, format: :short_year .item-pointer .item-content .bubble-stream{class: activity_class(idea)} .item-main{class: ('has-media' if idea.has_stream_media?)} - if idea.has_stream_media? .stream-media = link_to stream_image(idea), idea_path(idea) - if idea.stream_media_video? = link_to "▶".html_safe, idea_path(idea) .text .text-body = want_link(idea) .sub %span.actions = solution_count(idea) = me_too_link(idea)
![Page 20: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/20.jpg)
- cache [‘stream’, idea, current_user] do .all-the-codez = me_too_link(idea)
hit����������� ������������������ rate?
![Page 21: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/21.jpg)
key:����������� ������������������ [idea,����������� ������������������ user]
hit����������� ������������������ rate:����������� ������������������ 1����������� ������������������ /����������� ������������������ Idea.count*User.count
hit����������� ������������������ rate
![Page 22: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/22.jpg)
why����������� ������������������ hit����������� ������������������ rate����������� ������������������ matters
![Page 23: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/23.jpg)
= render_cached 'stream/idea', idea: idea, replace: {me_too_link: me_too_link(idea)}
- cache [‘stream’, idea] do .all-the-codez = cache_replace_key :me_too_link
cache_rocket
stream/_idea.html.haml
![Page 24: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/24.jpg)
:me_too_link
cache [‘stream’, idea]
![Page 25: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/25.jpg)
<div class="stream-item"> <div class="item-rail"> <div class="avatar-stream"> <a href="/neighbors/abarad" class="avatar-lnk" data-username="abarad"><img alt="Amy Barad" height="65" src="https://d30wms7jgjmff8.cloudfront.net/avatars/190/streama5e1bed52918ac859ed988618e7a2bad.jpg" width="65"></a> </div> <div class="mobile-meta show-for-small"> Suggested by <a href="/neighbors/abarad">Amy Barad</a><br> Jun 11, 2011 </div> </div> <div class="item-pointer"></div> <div class="item-content"> <div class="bubble-stream main-item"> <div class="has-media item-main"> <div class="stream-media"> <a href="/ideas/nola-the-ability-to-recycle-gl"><img alt="image" height="159" src="https://d30wms7jgjmff8.cloudfront.net/images/107/streamf97520b5053a463e8465195222e98a07.jpg" width="212"></a> </div> <div class="text"> <div class="text-body"> <a href="/ideas/nola-the-ability-to-recycle-gl">398 neighbors want the ability to recycle glass in New Orleans.</a> </div> <div class="sub"> <span class="actions"><a href="/ideas/nola-the-ability-to-recycle-gl#actions" class="btn white-border large"><strong>2</strong> actions</a></span><form action="/votes/803" class="button_to" method="post"> <div> <span class="actions"> <input name="_method" type="hidden" value="delete"> <input class="btn mint large" type="submit" value="Undo"> <input name="authenticity_token" type="hidden" value="vi66rEYBUkiqZVqss7DT/JhDbaN4GSdadEtk34ijRBg="> </span> </div></form> </div> </div> </div> <div class="rule-mint-xlt"></div> <div class="bubble-head new-supporters"> <span>New Supporters</span> <a href="/neighbors/brittwright" class="tiny-avatar-lnk"><img alt="Britt Wright" height="22" src="https://d30wms7jgjmff8.cloudfront.net/assets/avatar_medium_8.png" width="22"></a> <a href="/neighbors/rosemary" class="tiny-avatar-lnk"><img alt="Rosemary" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/25636/thumb0d559f628e6e05c8f32a179ba44e80a6." width="22"></a> <a href="/neighbors/willmarshall" class="tiny-avatar-lnk"><img alt="Will M." height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/26049/thumb2ae0e8a2760bcec545ae2655c497e2b1." width="22"></a> <a href="/neighbors/alex5" class="tiny-avatar-lnk"><img alt="Alex" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/26707/thumb511139a75432ee1b6dc9ad6f90b06ca2.jpg" width="22"></a> <a href="/neighbors/mike3" class="tiny-avatar-lnk"><img alt="Mike " height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/24145/thumbc9a0b03a4f25bcbb9f37de0486e4df10.png" width="22"></a> <a href="/neighbors/jaba4017" class="tiny-avatar-lnk"><img alt="Bill Arceneaux" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/3891/thumb6d95461aad25696fc0b4d69a4685f2f8.jpg" width="22"></a> <a href="/neighbors/faubourgstjohn" class="tiny-avatar-lnk"><img alt="Charlie London" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/203/thumb9872b2f76cdbcd64893f8855f73129cb.jpg" width="22"></a> <a href="/neighbors/andrewjameson" class="tiny-avatar-lnk"><img alt="Andrew Jameson" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/25316/thumb17689e5da8b64a01fc585438679037d4.jpg" width="22"></a> <a href="/neighbors/jenaoh1" class="tiny-avatar-lnk"><img alt="Jena Oh" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/25255/thumb1da559a045c471284e83cfded82f6e82." width="22"></a> <a href="/neighbors/rosemeistr" class="tiny-avatar-lnk"><img alt="rosemeistr" height="22" src="https://d30wms7jgjmff8.cloudfront.net/assets/avatar_medium_1.png" width="22"></a> </div> <div class="bubble-unit top-shadow hide-for-small bottom"> <span class="city-flag"><a href="/cities/nola">New Orleans</a></span> Suggested by <a href="/neighbors/abarad">Amy Barad</a> on Jun 11, 2011 </div> <div class="progress-flag"></div> </div> </div>
me_too_link
HTML����������� ������������������ on����������� ������������������ page
![Page 26: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/26.jpg)
<div class="stream-item"> <div class="item-rail"> <div class="avatar-stream"> <a href="/neighbors/abarad" class="avatar-lnk" data-username="abarad"><img alt="Amy Barad" height="65" src="https://d30wms7jgjmff8.cloudfront.net/avatars/190/streama5e1bed52918ac859ed988618e7a2bad.jpg" width="65"></a> </div> <div class="mobile-meta show-for-small"> Suggested by <a href="/neighbors/abarad">Amy Barad</a><br> Jun 11, 2011 </div> </div> <div class="item-pointer"></div> <div class="item-content"> <div class="bubble-stream main-item"> <div class="has-media item-main"> <div class="stream-media"> <a href="/ideas/nola-the-ability-to-recycle-gl"><img alt="image" height="159" src="https://d30wms7jgjmff8.cloudfront.net/images/107/streamf97520b5053a463e8465195222e98a07.jpg" width="212"></a> </div> <div class="text"> <div class="text-body"> <a href="/ideas/nola-the-ability-to-recycle-gl">398 neighbors want the ability to recycle glass in New Orleans.</a> </div> <div class="sub"> <span class="actions"><a href="/ideas/nola-the-ability-to-recycle-gl#actions" class="btn white-border large"><strong>2</strong> actions</a></span>
<cr me_too_link> </div> </div> </div> <div class="rule-mint-xlt"></div> <div class="bubble-head new-supporters"> <span>New Supporters</span> <a href="/neighbors/brittwright" class="tiny-avatar-lnk"><img alt="Britt Wright" height="22" src="https://d30wms7jgjmff8.cloudfront.net/assets/avatar_medium_8.png" width="22"></a> <a href="/neighbors/rosemary" class="tiny-avatar-lnk"><img alt="Rosemary" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/25636/thumb0d559f628e6e05c8f32a179ba44e80a6." width="22"></a> <a href="/neighbors/willmarshall" class="tiny-avatar-lnk"><img alt="Will M." height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/26049/thumb2ae0e8a2760bcec545ae2655c497e2b1." width="22"></a> <a href="/neighbors/alex5" class="tiny-avatar-lnk"><img alt="Alex" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/26707/thumb511139a75432ee1b6dc9ad6f90b06ca2.jpg" width="22"></a> <a href="/neighbors/mike3" class="tiny-avatar-lnk"><img alt="Mike " height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/24145/thumbc9a0b03a4f25bcbb9f37de0486e4df10.png" width="22"></a> <a href="/neighbors/jaba4017" class="tiny-avatar-lnk"><img alt="Bill Arceneaux" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/3891/thumb6d95461aad25696fc0b4d69a4685f2f8.jpg" width="22"></a> <a href="/neighbors/faubourgstjohn" class="tiny-avatar-lnk"><img alt="Charlie London" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/203/thumb9872b2f76cdbcd64893f8855f73129cb.jpg" width="22"></a> <a href="/neighbors/andrewjameson" class="tiny-avatar-lnk"><img alt="Andrew Jameson" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/25316/thumb17689e5da8b64a01fc585438679037d4.jpg" width="22"></a> <a href="/neighbors/jenaoh1" class="tiny-avatar-lnk"><img alt="Jena Oh" height="22" src="https://d30wms7jgjmff8.cloudfront.net/avatars/25255/thumb1da559a045c471284e83cfded82f6e82." width="22"></a> <a href="/neighbors/rosemeistr" class="tiny-avatar-lnk"><img alt="rosemeistr" height="22" src="https://d30wms7jgjmff8.cloudfront.net/assets/avatar_medium_1.png" width="22"></a> </div> <div class="bubble-unit top-shadow hide-for-small bottom"> <span class="city-flag"><a href="/cities/nola">New Orleans</a></span> Suggested by <a href="/neighbors/abarad">Amy Barad</a> on Jun 11, 2011 </div> <div class="progress-flag"></div> </div> </div></div>
me_too_link
HTML����������� ������������������ in����������� ������������������ memcache
![Page 27: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/27.jpg)
def replace_from_hash(hash) hash.each do |key, value| gsub! cache_replace_key(key), value.to_s endend
cache_rocketreplace_key = ‘<cr me_too_link>’html = ‘<form><div>etc...</div></form>’fragment.gsub! replace_key, html
![Page 28: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/28.jpg)
gsub!
![Page 29: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/29.jpg)
render_cached 'top', replace: 'inner'
a����������� ������������������ partial
= render ‘inner’= cache_replace_key :inner
top.html.haml
![Page 30: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/30.jpg)
render_cached 'top', replace: ['inner', ‘footer’]
partials
#here = cache_replace_key :inner#there = cache_replace_key :footer
top.html.haml
![Page 31: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/31.jpg)
render_cached 'top', replace: {key: a_helper(x)}
value
= cache_replace_key :keytop.html.haml
![Page 32: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/32.jpg)
render_cached 'item',collection: objects,replace: {key: ->(o){a_helper(o)}}
Proc����������� ������������������ for����������� ������������������ each����������� ������������������ item
= cache_replace_key :keyitem.html.haml
![Page 33: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/33.jpg)
def replace_item_hash(item, replace_hash) item_fragment = self.value.dup
replace_hash.each do |key, proc| item_fragment.gsub! cache_replace_key(key), proc.call(item) end
item_fragmentend
![Page 34: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/34.jpg)
gsub!
![Page 35: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/35.jpg)
extra����������� ������������������ string����������� ������������������ replacementdifferent����������� ������������������ render����������� ������������������ syntaxadds����������� ������������������ a����������� ������������������ dependency
cost
![Page 36: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/36.jpg)
cache����������� ������������������ more����������� ������������������ stuff>����������� ������������������ more����������� ������������������ hits>����������� ������������������ faster����������� ������������������ pages
less����������� ������������������ stuff����������� ������������������ in����������� ������������������ cache>����������� ������������������ more����������� ������������������ hits>����������� ������������������ less����������� ������������������ RAM
benefit
![Page 37: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/37.jpg)
No Caching 123 msRussian Doll* 67 msCacheRocket 113 msCacheRocket collection 82 ms
speed
![Page 38: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/38.jpg)
efficiency Hits MissesRussian Doll 1400 100CacheRocket 14 1
![Page 39: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/39.jpg)
efficiency Items SizeRussian Doll 100 120.9kCacheRocket 1 0.9k
![Page 40: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/40.jpg)
Cat
![Page 41: Rails HTML Fragment Caching with Cache Rocket](https://reader033.vdocument.in/reader033/viewer/2022042715/559c35ba1a28ab3d1a8b4623/html5/thumbnails/41.jpg)
https://github.com/neighborland/cache_rocket
https://github.com/teeparham/cache_benchmark
http://guides.rubyonrails.org/caching_with_rails.html
http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works
http://ninjasandrobots.com/rails-faster-partial-rendering-and-caching/
http://www.pal-blog.de/entwicklung/perl/memcached-statistics-stats-command.html
https://github.com/n8/multi_fetch_fragments
https://github.com/rails/cache_digests
references