Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Windycityrails page performance

6,424 views

Published on

A walkthrough of various application performance tuning tools and a good workflow for where to start, from a presentation at WindyCityRails 2011 in Chicago, IL.

See the video, and more Web and Ruby/Rails Performance info at www.RailsPerformance.com

-John McCaffrey

Published in: Technology, Design

Windycityrails page performance

  1. 1. Faster Page Performance John McCaffrey @J_McCaffreyhttp://spkr8.com/t/8314
  2. 2. Agenda• Intro• Performance 101• Performance tuning workflow• Performance features in Rails 3, 3.1• Considerations for Mobile and HTML 5• Q&A
  3. 3. Intro• Doing Rails since 2007• 4th time presenting at WindyCityRails o 2008: Advanced Firebug and JS unit testing o 2009: PDF Generation in Rails o 2010: Rails Performance Tuning o 2011: Faster Page Performance• Addicted to Performance Tuning• railsperformance.blogspot.com @J_McCaffrey• Feedback: speakerrate.com railsperformance@gmail.com
  4. 4. Intro• Doing Rails since 2007• 4th time presenting at WindyCityRails o 2008: Advanced Firebug and JS unit testing o 2009: PDF Generation in Rails o 2010: Rails Performance Tuning o 2011: Faster Page Performance• Addicted to Performance Tuning• railsperformance.blogspot.com @J_McCaffrey• Feedback: speakerrate.com railsperformance@gmail.com
  5. 5. Intro• Doing Rails since 2007• 4th time presenting at WindyCityRails o 2008: Advanced Firebug and JS unit testing o 2009: PDF Generation in Rails o 2010: Rails Performance Tuning o 2011: Faster Page Performance• Addicted to Performance Tuning• railsperformance.blogspot.com @J_McCaffrey• Feedback: speakerrate.com railsperformance@gmail.com
  6. 6. Intro
  7. 7. Intro• A little about you, and the people around you
  8. 8. Intro• A little about you, and the people around you• You are all smarter than I am
  9. 9. Intro• A little about you, and the people around you• You are all smarter than I am• Try hard to Network today, meet cool people
  10. 10. Intro• A little about you, and the people around you• You are all smarter than I am• Try hard to Network today, meet cool people• Eat lunch with someone new, invite someone into your ‘crowd’, go to the After Party!!
  11. 11. Quick Poll• Work on a Rails application• Have been doing Rails for less than 6 months? 1yr? 2yrs? 4yrs?• Testing Rspec? cucumber? Test::Unit? CI?• Write Javascript frequently? jQuery? Prototype? js testing?• Working with Rails 3 or Rails 3.1• Work on Mobile (native or web)• Working with HTML 5
  12. 12. Quick Poll• Raise your hand if you Want to learn more• Stand up if you’d like to meet up with others and share what you’ve learned
  13. 13. Quick Poll• Raise your hand if you Want to learn more• Stand up if you’d like to meet up with others and share what you’ve learned Don’t knock over your coffee!
  14. 14. Help me, Help you!!• Improving page loading time• Sql query tuning, indexes or DB tuning• Rails 3 and 3.1• HTML 5 and CSS 3• NoSQL
  15. 15. Introduce yourself (to someone new)Photo by @monty_ksycki
  16. 16. Introduce yourself (to someone new)Photo by @monty_ksycki
  17. 17. Introduce yourself (toyou’re from someone new)• Name & Where Photo by @monty_ksycki
  18. 18. Introduce yourself (toyou’re from someone new)• Name & Where• Most important thing you want to get out of WindyCityRails Photo by @monty_ksycki
  19. 19. Introduce yourself (toyou’re from someone new)• Name & Where• Most important thing you want to get out of WindyCityRails• Only 2mins for this!!!! Photo by @monty_ksycki
  20. 20. Agenda• Intro•• Performance 101 Performance tuning workflow• Performance features in Rails 3, 3.1• Considerations for Mobile and HTML 5
  21. 21. Performance Matterswww.strangeloopnetworks.com/web‐performance‐op4miza4on‐hub
  22. 22. Perf. statisticswww.strangeloopnetworks.com/web‐performance‐op4miza4on‐hub
  23. 23. Perf. statisticswww.strangeloopnetworks.com/web‐performance‐op4miza4on‐hub
  24. 24. Increased revenue 12%
  25. 25. http://blog.kissmetrics.com/loading-time/
  26. 26. So where do we start?
  27. 27. Drop some knowledge "Premature optimization is the root of all evil" -Donald Knuth
  28. 28. Is it premature?
  29. 29. Is it premature?Effort vs Value • Gzip • Adding database indexes • Optimizing images • Try nginx (or trinidad)
  30. 30. Measuring != Premature‘Good Enough’ metrics• Avg response time• Server Load• Memory footprint• Slow queries• Load capacity
  31. 31. Perf Tuning Pledge
  32. 32. Perf Tuning Pledge• “I will MEASURE before and after”
  33. 33. Perf Tuning Pledge• “I will MEASURE before and after”• “I will document and share the findings”
  34. 34. Perf Tuning Pledge• “I will MEASURE before and after”• “I will document and share the findings”• “WE will decide to monitor it, fix it, or just forget it”
  35. 35. Agenda• Intro• Performance 101• Performance tuning workflow• Performance features in Rails 3, 3.1• Considerations for Mobile and HTML 5
  36. 36. Perf tuning workflow• Page load• Application tuning• DB performance• Javascript• Architecture*
  37. 37. Improving page load
  38. 38. Improving page load Yslow (Firefox and Chrome) http://developer.yahoo.com/yslow/ Page speed (Firefox and Chrome) http://code.google.com/speed Dynatrace (IE and Firefox) http://ajax.dynatrace.com Webpagetest.org (IE, Chrome, Firefox)
  39. 39. Improving page load Yslow (Firefox and Chrome) http://developer.yahoo.com/yslow/ Page speed (Firefox and Chrome) http://code.google.com/speed Dynatrace (IE and Firefox) http://ajax.dynatrace.com Webpagetest.org (IE, Chrome, Firefox)
  40. 40. Improving page load Yslow (Firefox and Chrome) http://developer.yahoo.com/yslow/ Page speed (Firefox and Chrome) http://code.google.com/speed Dynatrace (IE and Firefox) http://ajax.dynatrace.com Webpagetest.org (IE, Chrome, Firefox)
  41. 41. Improving page load Yslow (Firefox and Chrome) http://developer.yahoo.com/yslow/ Page speed (Firefox and Chrome) http://code.google.com/speed Dynatrace (IE and Firefox) http://ajax.dynatrace.com Webpagetest.org (IE, Chrome, Firefox)
  42. 42. Improving page load Yslow (Firefox and Chrome) http://developer.yahoo.com/yslow/ Page speed (Firefox and Chrome) http://code.google.com/speed Dynatrace (IE and Firefox) http://ajax.dynatrace.com Webpagetest.org (IE, Chrome, Firefox)
  43. 43. Improving page load Yslow (Firefox and Chrome) http://developer.yahoo.com/yslow/ Page speed (Firefox and Chrome) http://code.google.com/speed Dynatrace (IE and Firefox) http://ajax.dynatrace.com Webpagetest.org (IE, Chrome, Firefox)80-85% of the time is spent on the front-end
  44. 44. Page load rules 1. Minimize HTTP Requests 2. Use a Content Delivery Network 3. Add an Expires or a Cache-Control Header 4. Gzip Components 5. Put StyleSheets at the Top 6. Put Scripts at the Bottom 7. Avoid CSS ExpressionsSteve Souders 8. Make JavaScript and CSS External 9. Reduce DNS Lookups 10. Minify JavaScript and CSS 11. Avoid Redirects 12. Remove Duplicate Scripts 13. Configure ETags 14. Make AJAX Cacheable 15. Use GET for AJAX Requests 16. Reduce the Number of DOM Elements 17. No 404s 18. Reduce Cookie Size
  45. 45. Waterfall 101
  46. 46. • Typically 80% of the browsers ‘effort’ is spent loading all the other stuff after the initial html
  47. 47. Waterfall 101
  48. 48. Waterfall 101
  49. 49. Waterfall 101
  50. 50. Waterfall 101
  51. 51. Waterfall 101Javascript execution is blocking the next download
  52. 52. Waterfall 101
  53. 53. Waterfall 101Css shouldn’t block,what’s going on here?
  54. 54. Waterfall 101<head> <title>base page</title> <link type="text/css" rel="stylesheet" href="http://tools.w3clubs.com/1.expires.css"> <!--[if IE 6 ]> <linktype="text/css" rel="stylesheet"href="http://tools.w3clubs.com/2.expires.css"> <![endif]--></head> www.phpied.com/conditional-comments-block-downloads
  55. 55. Waterfall 101<!--[if IE]><![endif]--><head><html lang="en"> <title>base page</title><head> type="text/css" rel="stylesheet" href="http://tools.w3clubs.com/1.expires.css"> <link <!--[if IE 6 page</title> <title>base ]> <link type="text/css" rel="stylesheet"href="http://tools.w3clubs.com/2.expires.css"> <linktype="text/css" rel="stylesheet" href="http://tools.w3clubs.com/1.expires.css"> <![endif]--> ]> <!--[if IE 6 <linktype="text/css" rel="stylesheet"href="http://tools.w3clubs.com/2.expires.css"></head> <![endif]--></head> www.phpied.com/conditional-comments-block-downloads
  56. 56. Save your Waterfall! HTTP Archive format (HAR)
  57. 57. Save your Waterfall! HTTP Archive format (HAR)• Export options www.softwareishard.com/blog/har-adopters • Firebug • IE9 • Chrome • Webpagetest.org• Har viewer www.softwareishard.com/har/viewer • Compare multiple files
  58. 58. Save your Waterfall! HTTP Archive format (HAR)• Export options www.softwareishard.com/blog/har-adopters • Firebug • IE9 • Chrome • Webpagetest.org• Har viewer www.softwareishard.com/har/viewer • Compare multiple filesDid I mention that its important to measure?
  59. 59. Solutions• Gzip• Combine and minify js and css• Load css first, js at the bottom• Optimize images and use css sprites• Use a cdn for static assets• Defer javascript loading
  60. 60. Deferred loading of javascript
  61. 61. Deferred loading of javascript• Load only the minimum necessary javascript first• Load the rest of the javascript asynchronously• Pre-load and pre-cache javascript and images for the next pages
  62. 62. Deferred loading of javascript• Load only the minimum necessary javascript first• Load the rest of the javascript asynchronously• Pre-load and pre-cache javascript and images for the next pages bit.ly/non-blocking-jswww.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking
  63. 63. Leverage✓ Those changes improve the performance across multiple requests✓ Well tested, well understood✓ Continues to be useful as new features are added, won’t get in your way
  64. 64. Leverage✓ Those changes improve the performance across multiple requests✓ Well tested, well understood✓ Continues to be useful as new features are added, won’t get in your way
  65. 65. Perf tuning workflow• Page load• Application tuning• DB performance• Javascript
  66. 66. Backend performance
  67. 67. Backend performance 2 seconds? What’s taking so long?
  68. 68. Tools• Request log analyzer• Splunk• New Relic• Rack::Bug• Built in Benchmark and profiling tools
  69. 69. What I’m looking for
  70. 70. What I’m looking for• What is the average response time• What is the slowest request• What request makes up the majority of the work the server is doing• Are there good candidates for caching?
  71. 71. Common culprits• Not leveraging the database• Too much memory• Too many queries• Generally slow code• Loading more fields than needed
  72. 72. N +1clients = Client.limit(10) clients.each do |client| puts client.address.postcodeend
  73. 73. N +1 1 query to clients = Client.limit(10)load the clients clients.each do |client| puts client.address.postcode end
  74. 74. N +1 1 query to clients = Client.limit(10)load the clients clients.each do |client| puts client.address.postcode end 1 query for each address (x10)
  75. 75. N +1 1 query to clients = Client.limit(10)load the clients clients.each do |client| puts client.address.postcode end 1 query for each address (x10) clients = Client.includes(:address).limit(10) clients.each do |client| puts client.address.postcode end
  76. 76. N +1 1 query to clients = Client.limit(10)load the clients clients.each do |client| puts client.address.postcode end 1 query to 1 query for each address (x10)load the clients clients = Client.includes(:address).limit(10) clients.each do |client| puts client.address.postcode end
  77. 77. N +1 1 query to clients = Client.limit(10)load the clients clients.each do |client| puts client.address.postcode end 1 query to 1 query for each address (x10)load the clients clients = Client.includes(:address).limit(10) clients.each do |client| puts client.address.postcode end 1 query to get all 10 Addresses!
  78. 78. Libraries
  79. 79. Libraries• Document why you have it• Remove unused, reduce dependencies• Pick between duplicate tools• Try to stay current• Rvm, bundler and git branches for testing• “Is it safe to upgrade that library” - find the right balance of tests to answer this
  80. 80. Perf tuning workflow• Page load• Application tuning• DB performance• Javascript
  81. 81. DB Tuning• Slow Queries• Not enough server resources• Not balanced for Read/Write usage
  82. 82. Tools• Rails log• Slow query log • launchpad.net/percona-toolkit• Explain• Server profiling (CPU, IO, Mem, etc)
  83. 83. ExplainAggregate (cost=154115.13..154115.14 rows=1 width=4) (actual time=4760.885..4760.886 rows=1 loops=1) ->Nested Loop Left Join (cost=0.00..154115.11 rows=9 width=4) (actual time=3262.981..4760.794 rows=2) Join Filter:(parts.id = lines_bills.part_id) ->Nested Loop Left Join (cost=0.00..154100.44 rows=9 width=8) (actual time=3262.954..4760.608 rows=2) ->Nested Loop (cost=0.00..153983.24 rows=8 width=4) (actual time=3262.940..4760.574 rows=2 loops=1) ->Seq Scan on bills (cost=0.00..153822.17 rows=11 width=4) (actual time=3262.813..4760.361 rows=2) Filter:(((bill_type)::text = Personal::text) AND (upper((ssn)::text) ~~ %333901151%::text)) ->Index Scan using lines_idx1 on lines (cost=0.00..14.63 rows=1 width=4) (actual time=0.093..0.094) Index Cond: (lines.bill_id = bills.id) Filter:((NOT lines.archived) AND ((lines.status)::text <> created::text)) ->Index Scan using lines_idx1 on lines lines_bills (cost=0.00..14.62 rows=2 width=8) Index Cond:(lines_bills.bill_id = bills.id) ->Seq Scan on parts (cost=0.00..1.28 rows=28 width=4) (actual time=0.010..0.045 rows=30 loops=2)Total runtime: 4761.401 ms
  84. 84. ExplainAggregate (cost=154115.13..154115.14 rows=1 width=4) (actual time=4760.885..4760.886 rows=1 loops=1) ->Nested Loop Left Join (cost=0.00..154115.11 rows=9 width=4) (actual time=3262.981..4760.794 rows=2) Join Filter:(parts.id = lines_bills.part_id) ->Nested Loop Left Join (cost=0.00..154100.44 rows=9 width=8) (actual time=3262.954..4760.608 rows=2) ->Nested Loop (cost=0.00..153983.24 rows=8 width=4) (actual time=3262.940..4760.574 rows=2 loops=1) ->Seq Scan on bills (cost=0.00..153822.17 rows=11 width=4) (actual time=3262.813..4760.361 rows=2) Filter:(((bill_type)::text = Personal::text) AND (upper((ssn)::text) ~~ %333901151%::text)) ->Index Scan using lines_idx1 on lines (cost=0.00..14.63 rows=1 width=4) (actual time=0.093..0.094) Index Cond: (lines.bill_id = bills.id) Filter:((NOT lines.archived) AND ((lines.status)::text <> created::text)) ->Index Scan using lines_idx1 on lines lines_bills (cost=0.00..14.62 rows=2 width=8) Index Cond:(lines_bills.bill_id = bills.id) ->Seq Scan on parts (cost=0.00..1.28 rows=28 width=4) (actual time=0.010..0.045 rows=30 loops=2)Total runtime: 4761.401 mschanged (upper(ssn) LIKE E%123456789%)to (ssn LIKE E123456789%) Total runtime: 7.579ms
  85. 85. ExplainAggregate (cost=154115.13..154115.14 rows=1 width=4) (actual time=4760.885..4760.886 rows=1 loops=1) ->Nested Loop Left Join (cost=0.00..154115.11 rows=9 width=4) (actual time=3262.981..4760.794 rows=2) Join Filter:(parts.id = lines_bills.part_id) ->Nested Loop Left Join (cost=0.00..154100.44 rows=9 width=8) (actual time=3262.954..4760.608 rows=2) ->Nested Loop (cost=0.00..153983.24 rows=8 width=4) (actual time=3262.940..4760.574 rows=2 loops=1) ->Seq Scan on bills (cost=0.00..153822.17 rows=11 width=4) (actual time=3262.813..4760.361 rows=2) Filter:(((bill_type)::text = Personal::text) AND (upper((ssn)::text) ~~ %333901151%::text)) ->Index Scan using lines_idx1 on lines (cost=0.00..14.63 rows=1 width=4) (actual time=0.093..0.094) Index Cond: (lines.bill_id = bills.id) Filter:((NOT lines.archived) AND ((lines.status)::text <> created::text)) ->Index Scan using lines_idx1 on lines lines_bills (cost=0.00..14.62 rows=2 width=8) Index Cond:(lines_bills.bill_id = bills.id) ->Seq Scan on parts (cost=0.00..1.28 rows=28 width=4) (actual time=0.010..0.045 rows=30 loops=2)Total runtime: 4761.401 mschanged (upper(ssn) LIKE E%123456789%)to (ssn LIKE E123456789%) Total runtime: 7.579msthen to (ssn = E123456789) Total runtime: 1.696ms
  86. 86. Culprits
  87. 87. Culprits• Too many queries• No indexes on the key data• Not optimized for how the db ‘thinks’• Not enough server memory for sorting• Trying to do too much in one query
  88. 88. Testing
  89. 89. Testing• Measure first!• Make performance tuning changes in the most tested parts of the app• Have the most important parts of your app well-tested, so tuning will be easier• Well-tested code tends to be well factored
  90. 90. Perf tuning workflow• Page load• Application tuning• DB performance• Javascript
  91. 91. Javascript is powerful
  92. 92. Javascript is powerful• Most hate for javascript is really a hatred of the browser and DOM interaction
  93. 93. Javascript is powerful• Most hate for javascript is really a hatred of the browser and DOM interaction• Javascript is driving a lot of very cool things
  94. 94. Javascript is powerful• Most hate for javascript is really a hatred of the browser and DOM interaction• Javascript is driving a lot of very cool things • Node.js
  95. 95. Javascript is powerful• Most hate for javascript is really a hatred of the browser and DOM interaction• Javascript is driving a lot of very cool things • Node.js • Backbone
  96. 96. Javascript is powerful• Most hate for javascript is really a hatred of the browser and DOM interaction• Javascript is driving a lot of very cool things • Node.js • Backbone • sproutCore
  97. 97. High performance js• UI thread is responsible for js and UI updates• Understand Repaint and Reflow triggers• Benchmarks for browser performance• Dom Scripting• Memory and cpu usage
  98. 98. Javascript profiling• Dynatrace• Google Speed tracer• Firebug profiler
  99. 99. Dynatrace Ajax (IE and Firefox)http://blog.dynatrace.com/2010/07/22/ie-compatibility-view-how-to-identify-performance- problems-between-ie-versions/
  100. 100. Dynatrace Ajax (IE and Firefox)http://blog.dynatrace.com/2010/07/22/ie-compatibility-view-how-to-identify-performance- problems-between-ie-versions/
  101. 101. jQuery Top Issues
  102. 102. jQuery Top Issues• Poor selector usage • $(‘#Id, form, input’) Id and element are fast • $(‘.classname’) causes full scan in IE5-8
  103. 103. jQuery Top Issues• Poor selector usage • $(‘#Id, form, input’) Id and element are fast • $(‘.classname’) causes full scan in IE5-8• show() and hide() often slower than .addClass(“show”) or .addClass(“hide”)
  104. 104. jQuery Top Issues• Poor selector usage • $(‘#Id, form, input’) Id and element are fast • $(‘.classname’) causes full scan in IE5-8• show() and hide() often slower than .addClass(“show”) or .addClass(“hide”)• .each() often slower than regular ‘for’ loop
  105. 105. jQuery Top Issues• Poor selector usage • $(‘#Id, form, input’) Id and element are fast • $(‘.classname’) causes full scan in IE5-8• show() and hide() often slower than .addClass(“show”) or .addClass(“hide”)• .each() often slower than regular ‘for’ loop• Avoid extra queries by caching selector
  106. 106. jQuery Top Issues• Poor selector usage • $(‘#Id, form, input’) Id and element are fast • $(‘.classname’) causes full scan in IE5-8• show() and hide() often slower than .addClass(“show”) or .addClass(“hide”)• .each() often slower than regular ‘for’ loop• Avoid extra queries by caching selector• Avoid manipulating the Dom in a loop, try to append all at once (with a wrapping element)
  107. 107. Browser Comparison
  108. 108. Browser Comparison• jsperf.com • Compare js performance across browsers • http://jsperf.com/queryselectorall-vs- getelementsbytagname
  109. 109. Browser Comparison• jsperf.com • Compare js performance across browsers • http://jsperf.com/queryselectorall-vs- getelementsbytagname• jsfiddle.net (full page structure) • http://jsfiddle.net/addyosmani/BFeMN/
  110. 110. Browser Comparison• jsperf.com • Compare js performance across browsers • http://jsperf.com/queryselectorall-vs- getelementsbytagname• jsfiddle.net (full page structure) • http://jsfiddle.net/addyosmani/BFeMN/These tools make benchmarks easier and repeatable
  111. 111. Agenda• Intro• Performance 101• Performance tuning workflow• Performance features in Rails 3, 3.1• Considerations for Mobile and HTML 5
  112. 112. Performance features in Rails 3• Separation of framework, only load what you need• New Active Record Arel query structure • http://www.slideshare.net/tenderlove/zomg-why- is-this-code-so-slow• Bundler• Ruby 1.9.2 (with patch for faster Rails 3 load)
  113. 113. Performance features in Rails 3.1
  114. 114. Performance features in Rails 3.1• JQuery by default
  115. 115. Performance features in Rails 3.1• JQuery by default• Prepared statement caching
  116. 116. Performance features in Rails 3.1• JQuery by default• Prepared statement caching• New Asset Pipeline
  117. 117. Performance features in Rails 3.1• JQuery by default• Prepared statement caching• New Asset Pipeline • railscasts.com/episodes/279-understanding-the-asset-pipeline
  118. 118. Performance features in Rails 3.1• JQuery by default• Prepared statement caching• New Asset Pipeline • railscasts.com/episodes/279-understanding-the-asset-pipeline• Http Streaming
  119. 119. Performance features in Rails 3.1• JQuery by default• Prepared statement caching• New Asset Pipeline • railscasts.com/episodes/279-understanding-the-asset-pipeline• Http Streaming • railscasts.com/episodes/266-http-streaming
  120. 120. Html 5 is a big deal!• More tags and native behavior• Native form elements• Client side Validation• http://slides.html5rocks.com• http://mrdoob.com/91/Ball_Pool• http://bodybrowser.googlelabs.com• http://www.chromeexperiments.com/
  121. 121. Mobile
  122. 122. Mobile• Good for ‘desktop’ and mobile
  123. 123. Mobile• Good for ‘desktop’ and mobile • Reduce network calls
  124. 124. Mobile• Good for ‘desktop’ and mobile • Reduce network calls • Only load what you need
  125. 125. Mobile• Good for ‘desktop’ and mobile • Reduce network calls • Only load what you need • Cache as much as you can (HTML5 AppCache)
  126. 126. Mobile• Good for ‘desktop’ and mobile • Reduce network calls • Only load what you need • Cache as much as you can (HTML5 AppCache)• Specific to mobile
  127. 127. Mobile• Good for ‘desktop’ and mobile • Reduce network calls • Only load what you need • Cache as much as you can (HTML5 AppCache)• Specific to mobile • Javascript is roughly 10X slower on mobile
  128. 128. Mobile• Good for ‘desktop’ and mobile • Reduce network calls • Only load what you need • Cache as much as you can (HTML5 AppCache)• Specific to mobile • Javascript is roughly 10X slower on mobile • Click events delay for 300-500ms, use touch instead
  129. 129. Mobile• Good for ‘desktop’ and mobile • Reduce network calls • Only load what you need • Cache as much as you can (HTML5 AppCache)• Specific to mobile • Javascript is roughly 10X slower on mobile • Click events delay for 300-500ms, use touch instead • Smaller Cache (IOS only caches pages under 25kb unzipped)
  130. 130. Browser referenceshttp://developer.yahoo.com/yslow/http://code.google.com/speedhttp://ajax.dynatrace.comWebpagetest.orghttp://ajaxian.com/archives/when-does-javascript-trigger-reflows-and-rendering
  131. 131. jQuery• http://addyosmani.com/jqprovenperformance• http://www.learningjquery.com/2010/05/now- you-see-me-showhide-performance• http://www.learningjquery.com/2009/03/43439- reasons-to-use-append-correctly
  132. 132. javascript• Find a mentor: http://jsmentors.com• play around: http://jsfiddle.net/addyosmani/BFeMN• run tests and share them: jsperf.com• speed of different tools: dante.dojotoolkit.org/taskspeed
  133. 133. Thank You! Any Questions? railsperformance.blogspot.comrailsperformance@gmail.com @J_McCaffrey

×