Slide 1

Slide 1 text

Web Performance and Optimization in Rails

Slide 2

Slide 2 text

Constantin Hofstetter
 github.com/consti twitter.com/consti consti.de claimspotting (yc s08)

Slide 3

Slide 3 text

Backend Frontend How do we measure our application performance? How can we optimize our application?

Slide 4

Slide 4 text

Backend::Measure

Slide 5

Slide 5 text

Backend::Measure NewRelic RPM (Developer mode) gem ‘newrelic_rpm’ /newrelic in development Comes free with any
 version of New Relic

Slide 6

Slide 6 text

Backend::Measure rack-mini-profiler gem ‘rack-mini-profiler’ + flamegraph gem ‘flamegraph’ /?pp=flamegraph

Slide 7

Slide 7 text

Backend::Measure Derailed Benchmarks gem 'derailed' Benchmark Rails app, especially
 memory consumption

Slide 8

Slide 8 text

Backend::Measure Does the application have a memory leak?
 What causes the memory leak? How Ruby Uses Memory
 http://www.sitepoint.com/ruby-uses-memory/

Slide 9

Slide 9 text

Backend::Optimize

Slide 10

Slide 10 text

Backend::Optimize lol_dba gem install lol_dba Scan application for missing indices postgres query to find missing indices:
 http://is.gd/blue_elephant_pg

Slide 11

Slide 11 text

bullet Backend::Optimize gem ‘bullet’ Watch application for missing or
 unnecessary eager loadings (n+1)

Slide 12

Slide 12 text

Frontend::Measure

Slide 13

Slide 13 text

WebPagetest http://www.webpagetest.org Frontend::Measure

Slide 14

Slide 14 text

Google PageSpeed Insights Frontend::Measure

Slide 15

Slide 15 text

Frontend::Optimize

Slide 16

Slide 16 text

Static Assets File Uploads Other Optimizations Frontend::Optimize

Slide 17

Slide 17 text

Frontend::Optimize::StaticAssets Optimize Delivery • Leverage browser caching • Store on file storage web service (e.g. S3) • Use content delivery network (e.g. CloudFront) Create an S3 bucket and a CloudFront instance
 that points to the bucket. Use the asset_sync gem. Set config.action_controller.asset_host.

Slide 18

Slide 18 text

Frontend::Optimize::StaticAssets # in your asset_sync.rb config.custom_headers = { # for fonts and svg, you have to set Access-Control-Allow-Origin '.*\.[svg|woff|ttf|eot]' => { 'Access-Control-Allow-Origin' => '*', cache_control: "public, max-age=#{ 1.month.to_i }", expires: nil }, # Everything else, set cache-control to max-age 1 month '.*' => { cache_control: "public, max-age=#{ 1.month.to_i }", expires: nil } } asset_sync • Set CacheControl (time in seconds the client is allowed to cache
 the resource). Don’t use Expires (future date) • Set Access-Control-Allow-Origin for fonts and SVG

Slide 19

Slide 19 text

Frontend::Optimize::StaticAssets Minimize Payload text files images

Slide 20

Slide 20 text

Frontend::Optimize::StaticAssets # in your asset_sync.rb config.gzip_compression = true Text compression • Enable gzip_compression • S3 will deliver compressed version if GET request
 includes `Accept-Encoding: gzip` Both, the original and gzipped
 version will be synced to S3.

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

Frontend::Optimize::StaticAssets Image compression • Lossless and (optional) lossy compression • ImageOptim (drag and drop assets/images folder) • ImageOptim-CLI with git pre-commit hook # in your_project/.git/hooks/pre-commit images=$(git diff --exit-code --cached --name-only
 --diff-filter=ACM -- '*.png' ‘*.jpg' ‘*.jpeg' '*.gif')
 $(exit $?) || echo $images | imageoptim && git add $images Also converts PNG-24 to
 PNG-8+alpha images.

Slide 23

Slide 23 text

Frontend::Optimize::StaticAssets 400kb 130kb
 (32% of original file size)

Slide 24

Slide 24 text

Static Assets File Uploads Other Optimizations Frontend::Optimize

Slide 25

Slide 25 text

Frontend::Optimize::FileUploads Optimize Upload • Have browser client upload directly to S3 • Add ActiveJob to postprocess files • Resize images on client (e.g. jQuery-File-Upload)

Slide 26

Slide 26 text

Frontend::Optimize::ImageUploads Minimize Payload Optimize images when post-processing # in config/initializers/carrierwave.rb module CarrierWave::MiniMagick def optimize manipulate! do |img| img.strip img.interlace(“Plane”) # makes image progressive if JPG img.quality(90) img = yield(img) if block_given? img end end end # in ImageUploader version :preview do process :optimize end Thumbnails should be
 stored as baseline and
 not as progressive JPGs.

Slide 27

Slide 27 text

Frontend::Optimize::ImageUploads Optimize Delivery • Store on file storage web service (e.g. S3) • Use content delivery network (e.g. CloudFront) • Leverage browser caching # in config/initializers/carrierwave.rb CarrierWave.configure do |config| config.asset_host = “http://d12345678.cloudfront.net” config.fog_attributes = { 'Cache-Control' => 1.month.to_i } … end

Slide 28

Slide 28 text

Static Assets File Uploads Other Optimizations Frontend::Optimize

Slide 29

Slide 29 text

Frontend::Optimize Turbolinks is great! It’s even better with Turbolinks.enableTransitionCache() Other Optimizations • Minimize external resources (e.g. Google Fonts) • Use Turbolinks

Slide 30

Slide 30 text

HTTP/2 multiplexing serve multiple resources in one response binary based protocol – allows for smaller payload header compression – compression to the max server push – proactively send resources to client

Slide 31

Slide 31 text

Backend • Profile application • Use tools for quick
 wins Frontend • Webpagetest etc. • Compress resources • Use CDN Things to come • Keep HTTP/2
 features in mind

Slide 32

Slide 32 text

We’re always hiring self-motivated
 Rails and Front-end developers. Just send an email to [email protected]