SlideShare a Scribd company logo
1 of 39
Download to read offline
Intro to Rails #webperf
teu rhu man
@ ama
ruby -v
                1.9.2
            1.8.7
1.9.3
1.8.6
require ‘benchmark’
  MRI 1.9.3
              MRI 1.8.7
              RBX 1.2.4
         JRuby 1.6.7
Passengers,
Unicorns,
Pumas.
Oh my!
Passenger
Simple to operate.
Simple configuration.
Handles worker management.
Great for multi-app environments.
Great for low resource environments.
Attached to Nginx/Apache HTTPD.
Unicorn
Highly configurable.
Independent of front-end web server.
Master will reap children on timeout.
Great for single app environments.
Allows for zero downtime deploys.
Puma
Based on Mongrel.
Designed for concurrency.
Uses real threads.
Anatomy of a Web Request
Link Clicked                DOM Loaded


Redirects Cache DNS TCP SSL Request App Response DOM Render




                                First Byte        Load
80% in Front-End
Inside the Web App
Database Performance
Lazy Loading
๏   ORMs make it easy to access data.
๏   Easy access to data can create issues.
๏   Performance issues are hard to see in
    development mode.
๏   Look to production metrics to optimize
    and refactor.
N+1 Query Creep
# app/models/customer.rb
class Customer < ActiveRecord::Base
  has_many :addresses
end

# app/models/address.rb
class Address < ActiveRecord::Base
  belongs_to :customer
end

# app/controllers/customers_controller.rb
class CustomersController < ApplicationController
  def index
      @customers = Customer.all
  end
end

# app/views/customers/index.html.erb
<% @customers.each do |customer| %>
  <%= content_tag :h1, customer.name %>
<% end %>
N+1 Query Creep
# app/views/customers/index.html.erb
<% @customers.each do |customer| %>
  <%= content_tag :h1, customer.name %>
  <%= content_tag :h2, customer.addresses.first.city %>
<% end %>


If @customers has 100 records, you'll have 101 queries:
SELECT "customers".* FROM "customers"
SELECT "addresses".* FROM "addresses" WHERE   "addresses"."customer_id" = 1 AND
  "addresses"."primary" = 't' LIMIT 1
SELECT "addresses".* FROM "addresses" WHERE   "addresses"."customer_id" = 2 AND
  "addresses"."primary" = 't' LIMIT 1
SELECT "addresses".* FROM "addresses" WHERE   "addresses"."customer_id" = 3 AND
  "addresses"."primary" = 't' LIMIT 1
...
...
SELECT "addresses".* FROM "addresses" WHERE   "addresses"."customer_id" = 100
  AND "addresses"."primary" = 't' LIMIT 1
Eager Load Instead
# app/controllers/customers_controller.rb
class CustomersController < ApplicationController
  def index
      @customers = Customer.includes(:addresses).all
  end
end

If @customers has 100 records, now we only have 2 queries:
SELECT "customers".* FROM "customers"
SELECT "addresses".* FROM "addresses" WHERE   "addresses"."customer_id" IN (1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,   15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,   34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,   53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,   72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,   91, 92, 93, 94, 95, 96, 97, 98,
99, 100)
Finding N+1
Missing Indexes
๏   Searching a 1,000 row table with an
    index is 100x faster than searching
    without.
๏   Put indexes anywhere you might need to
    query; less is not more with indexes.
๏   Writing an index will lock your tables.
Missing Indexes Hurt
Indexes are Easy
# db/migrate/20120201040247_add_index_for_shop_id_on_orders.rb

class AddIndexForShopIdOnOrders < ActiveRecord::Migration
  def change
      add_index :orders, :shop_id
  end
end
Cache All The Things
Page Caching
# app/controllers/products_controller.rb
class ProductsController < ActionController

  caches_page :index

  def index
    @products = Products.all
  end

  def create
    expire_page :action => :index
  end

end

# /opt/nginx/conf/nginx.conf
location / {
  gzip_static on;
}
Action Caching
# app/controllers/products_controller.rb
class ProductsController < ActionController

  before_filter :authenticate
  caches_action :index

  def index
    @products = Product.all
  end

  def create
    expire_action :action => :index
  end

end
Fragment Caching
# app/views/products/index.html.erb

<% Order.find_recent.each do |o| %>
  <%= o.buyer.name %> bought <%= o.product.name %>
<% end %>

<% cache(‘all_products’) do %>
  All available products:
  <% Product.all.each do |p| %>
    <%= link_to p.name, product_url(p) %>
  <% end %>
<% end %>

# app/controllers/products_controller.rb
class ProductsController < ActionController

  def update
    expire_fragment(‘all_products’)
  end

end
Expiring Caches
    is Hard
Russian Doll Caching
# app/views/products/show.html.erb
<% cache product do %>
  Product options:
  <%= render product.options %>
<% end %>

# app/views/options/_option.html.erb
<% cache option do %>
  <%= option.name %>
  <%= option.description %>
<% end %>

# app/models/product.rb
class Product < ActiveRecord::Base
  has_many :options
end

# app/models/option.rb
class Option < ActiveRecord::Base
  belongs_to :product, touch: true
end
Background Jobs
Procrastinate
Reporting.
Sending email.
Processing images.
Call external services.
Building & Expiring Caches.
Rescued by Resque
class ReferralProcessor
  @queue = :referrals_queue

  def self.perform(schema_name, order_item_id)
    order_item = OrderItem.find(order_item_id)
    order = order_item.order
    user = order.user

    credit = AccountCredit.credit(order_item.unit_price, user, 'referral')
    credit.message = I18n.t('account_credits.predefined_messages.referral',
                            :description => order_item.description)
    credit.save!

    debit = Transaction.account_debit(credit.amount, user)
    debit.order = order
    debit.save!

    order.issue_refund(return_to_inventory: false, gateway_first: true,
                       cancel_items: false, cancel_certificates: false,
                       amount: credit.amount, as: 'original', notify_user: false)

    if user.receives_mail_for?(:referral_purchase)
      SystemMailer.referral_refund(order_item, credit).deliver
    end
  end
end
Get in Line
class ReferralObserver < ActiveRecord::Observer

  def after_create(referral)
    Resque.enqueue_in(1.day, ReferralProcessor, referral.item.id)
  end

end



# Get it started
$ PIDFILE=./resque.pid 
  BACKGROUND=yes 
  QUEUE=referrals_queue 
  rake environment resque:work
It’s Free in Rails 4

Establishing basic Queue API.
Implement push and pop.
Easily swap out for Resque, Sidekiq,
Delayed job.
What’s One More Second?
7%
Fewer Conversions
11%
Fewer Page Views
Time is
Money
Monitor your applications.
Performance is not set it and forget it.
Database indexes are cheap, make more.
Cache something, somewhere.
Push work off to the background.
Don’t neglect front-end performance.
Q?
30-day free trial at
newrelic.com/30

More Related Content

What's hot

Behavior Driven Development - How To Start with Behat
Behavior Driven Development - How To Start with BehatBehavior Driven Development - How To Start with Behat
Behavior Driven Development - How To Start with Behat
imoneytech
 

What's hot (20)

Ruby For Startups
Ruby For StartupsRuby For Startups
Ruby For Startups
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
สปริงเฟรมเวิร์ค4.1
สปริงเฟรมเวิร์ค4.1สปริงเฟรมเวิร์ค4.1
สปริงเฟรมเวิร์ค4.1
 
Angular Performance: Then, Now and the Future. Todd Motto
Angular Performance: Then, Now and the Future. Todd MottoAngular Performance: Then, Now and the Future. Todd Motto
Angular Performance: Then, Now and the Future. Todd Motto
 
Using of TDD practices for Magento
Using of TDD practices for MagentoUsing of TDD practices for Magento
Using of TDD practices for Magento
 
REST API for your WP7 App
REST API for your WP7 AppREST API for your WP7 App
REST API for your WP7 App
 
Developing New Widgets for your Views in Owl
Developing New Widgets for your Views in OwlDeveloping New Widgets for your Views in Owl
Developing New Widgets for your Views in Owl
 
Introduction to Ember.js and how we used it at FlowPro.io
Introduction to Ember.js and how we used it at FlowPro.ioIntroduction to Ember.js and how we used it at FlowPro.io
Introduction to Ember.js and how we used it at FlowPro.io
 
Angularjs Performance
Angularjs PerformanceAngularjs Performance
Angularjs Performance
 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experienced
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Webapps without the web
Webapps without the webWebapps without the web
Webapps without the web
 
Owl: The New Odoo UI Framework
Owl: The New Odoo UI FrameworkOwl: The New Odoo UI Framework
Owl: The New Odoo UI Framework
 
test
testtest
test
 
Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet
 
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovygreach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
 
Automated Testing in EmberJS
Automated Testing in EmberJSAutomated Testing in EmberJS
Automated Testing in EmberJS
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
Behavior Driven Development - How To Start with Behat
Behavior Driven Development - How To Start with BehatBehavior Driven Development - How To Start with Behat
Behavior Driven Development - How To Start with Behat
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop
 

Viewers also liked (8)

Why Developers Dislike Ad Hoc Data Requests
Why Developers Dislike Ad Hoc Data RequestsWhy Developers Dislike Ad Hoc Data Requests
Why Developers Dislike Ad Hoc Data Requests
 
New Relic 2011 WHITEPAPER
New Relic 2011 WHITEPAPERNew Relic 2011 WHITEPAPER
New Relic 2011 WHITEPAPER
 
New Relic Zapier Case Study Platform
New Relic Zapier Case Study PlatformNew Relic Zapier Case Study Platform
New Relic Zapier Case Study Platform
 
APM for Enterprise WhitePaper from New Relic
APM for Enterprise WhitePaper from New RelicAPM for Enterprise WhitePaper from New Relic
APM for Enterprise WhitePaper from New Relic
 
New Relic BeenVerified Case Study
New Relic BeenVerified Case StudyNew Relic BeenVerified Case Study
New Relic BeenVerified Case Study
 
New Relic Cure.org Case Study
New Relic Cure.org Case StudyNew Relic Cure.org Case Study
New Relic Cure.org Case Study
 
Platform Plugins Infographic
Platform Plugins InfographicPlatform Plugins Infographic
Platform Plugins Infographic
 
Atelier conference 10 octobre - voyages caritatifs
Atelier conference 10 octobre - voyages caritatifsAtelier conference 10 octobre - voyages caritatifs
Atelier conference 10 octobre - voyages caritatifs
 

Similar to Intro to-rails-webperf

How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
fiyuer
 

Similar to Intro to-rails-webperf (20)

6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performance
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-public
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatterns
 
The Rails Way
The Rails WayThe Rails Way
The Rails Way
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Advanced RESTful Rails
Advanced RESTful RailsAdvanced RESTful Rails
Advanced RESTful Rails
 
Advanced RESTful Rails
Advanced RESTful RailsAdvanced RESTful Rails
Advanced RESTful Rails
 
performance vamos dormir mais?
performance vamos dormir mais?performance vamos dormir mais?
performance vamos dormir mais?
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on Rails
 
Ruby on Rails + AngularJS + Twitter Bootstrap
Ruby on Rails + AngularJS + Twitter BootstrapRuby on Rails + AngularJS + Twitter Bootstrap
Ruby on Rails + AngularJS + Twitter Bootstrap
 
Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
 
Phoenix for Rails Devs
Phoenix for Rails DevsPhoenix for Rails Devs
Phoenix for Rails Devs
 
Ruby on Rails: Coding Guideline
Ruby on Rails: Coding GuidelineRuby on Rails: Coding Guideline
Ruby on Rails: Coding Guideline
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le Wagon
 
Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in Rails
 

More from New Relic

More from New Relic (20)

7 Tips & Tricks to Having Happy Customers at Scale
7 Tips & Tricks to Having Happy Customers at Scale7 Tips & Tricks to Having Happy Customers at Scale
7 Tips & Tricks to Having Happy Customers at Scale
 
7 Tips & Tricks to Having Happy Customers at Scale
7 Tips & Tricks to Having Happy Customers at Scale7 Tips & Tricks to Having Happy Customers at Scale
7 Tips & Tricks to Having Happy Customers at Scale
 
New Relic University at Future Stack Tokyo 2019
New Relic University at Future Stack Tokyo 2019New Relic University at Future Stack Tokyo 2019
New Relic University at Future Stack Tokyo 2019
 
FutureStack Tokyo 19 -[事例講演]株式会社リクルートライフスタイル:年間9300万件以上のサロン予約を支えるホットペッパービューティ...
FutureStack Tokyo 19 -[事例講演]株式会社リクルートライフスタイル:年間9300万件以上のサロン予約を支えるホットペッパービューティ...FutureStack Tokyo 19 -[事例講演]株式会社リクルートライフスタイル:年間9300万件以上のサロン予約を支えるホットペッパービューティ...
FutureStack Tokyo 19 -[事例講演]株式会社リクルートライフスタイル:年間9300万件以上のサロン予約を支えるホットペッパービューティ...
 
FutureStack Tokyo 19 -[New Relic テクニカル講演]モニタリングと可視化がデジタルトランスフォーメーションを救う! - サ...
FutureStack  Tokyo 19 -[New Relic テクニカル講演]モニタリングと可視化がデジタルトランスフォーメーションを救う! - サ...FutureStack  Tokyo 19 -[New Relic テクニカル講演]モニタリングと可視化がデジタルトランスフォーメーションを救う! - サ...
FutureStack Tokyo 19 -[New Relic テクニカル講演]モニタリングと可視化がデジタルトランスフォーメーションを救う! - サ...
 
FutureStack Tokyo 19 -[特別講演]システム開発によろこびと驚きの連鎖を
FutureStack Tokyo 19 -[特別講演]システム開発によろこびと驚きの連鎖をFutureStack Tokyo 19 -[特別講演]システム開発によろこびと驚きの連鎖を
FutureStack Tokyo 19 -[特別講演]システム開発によろこびと驚きの連鎖を
 
FutureStack Tokyo 19 -[パートナー講演]アマゾン ウェブ サービス ジャパン株式会社: New Relicを活用したAWSへのアプリ...
FutureStack Tokyo 19 -[パートナー講演]アマゾン ウェブ サービス ジャパン株式会社: New Relicを活用したAWSへのアプリ...FutureStack Tokyo 19 -[パートナー講演]アマゾン ウェブ サービス ジャパン株式会社: New Relicを活用したAWSへのアプリ...
FutureStack Tokyo 19 -[パートナー講演]アマゾン ウェブ サービス ジャパン株式会社: New Relicを活用したAWSへのアプリ...
 
FutureStack Tokyo 19_インサイトとデータを組織の力にする_株式会社ドワンゴ 池田 明啓 氏
FutureStack Tokyo 19_インサイトとデータを組織の力にする_株式会社ドワンゴ 池田 明啓 氏FutureStack Tokyo 19_インサイトとデータを組織の力にする_株式会社ドワンゴ 池田 明啓 氏
FutureStack Tokyo 19_インサイトとデータを組織の力にする_株式会社ドワンゴ 池田 明啓 氏
 
Three Monitoring Mistakes and How to Avoid Them
Three Monitoring Mistakes and How to Avoid ThemThree Monitoring Mistakes and How to Avoid Them
Three Monitoring Mistakes and How to Avoid Them
 
Intro to Multidimensional Kubernetes Monitoring
Intro to Multidimensional Kubernetes MonitoringIntro to Multidimensional Kubernetes Monitoring
Intro to Multidimensional Kubernetes Monitoring
 
FS18 Chicago Keynote
FS18 Chicago Keynote FS18 Chicago Keynote
FS18 Chicago Keynote
 
SRE-iously
SRE-iouslySRE-iously
SRE-iously
 
10 Things You Can Do With New Relic - Number 9 Will Shock You
10 Things You Can Do With New Relic - Number 9 Will Shock You10 Things You Can Do With New Relic - Number 9 Will Shock You
10 Things You Can Do With New Relic - Number 9 Will Shock You
 
Ground Rules for Code Reviews
Ground Rules for Code ReviewsGround Rules for Code Reviews
Ground Rules for Code Reviews
 
Understanding Microservice Latency for DevOps Teams: An Introduction to New R...
Understanding Microservice Latency for DevOps Teams: An Introduction to New R...Understanding Microservice Latency for DevOps Teams: An Introduction to New R...
Understanding Microservice Latency for DevOps Teams: An Introduction to New R...
 
Monitor all your Kubernetes and EKS stack with New Relic
Monitor all your Kubernetes and EKS stack with New Relic	Monitor all your Kubernetes and EKS stack with New Relic
Monitor all your Kubernetes and EKS stack with New Relic
 
Host for the Most: Cloud Cost Optimization
Host for the Most: Cloud Cost OptimizationHost for the Most: Cloud Cost Optimization
Host for the Most: Cloud Cost Optimization
 
New Relic Infrastructure in the Real World: AWS
New Relic Infrastructure in the Real World: AWSNew Relic Infrastructure in the Real World: AWS
New Relic Infrastructure in the Real World: AWS
 
Best Practices for Measuring your Code Pipeline
Best Practices for Measuring your Code PipelineBest Practices for Measuring your Code Pipeline
Best Practices for Measuring your Code Pipeline
 
Top Three Mistakes People Make with Monitoring
Top Three Mistakes People Make with MonitoringTop Three Mistakes People Make with Monitoring
Top Three Mistakes People Make with Monitoring
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 

Intro to-rails-webperf

  • 1. Intro to Rails #webperf
  • 2.
  • 4. ruby -v 1.9.2 1.8.7 1.9.3 1.8.6
  • 5. require ‘benchmark’ MRI 1.9.3 MRI 1.8.7 RBX 1.2.4 JRuby 1.6.7
  • 7. Passenger Simple to operate. Simple configuration. Handles worker management. Great for multi-app environments. Great for low resource environments. Attached to Nginx/Apache HTTPD.
  • 8. Unicorn Highly configurable. Independent of front-end web server. Master will reap children on timeout. Great for single app environments. Allows for zero downtime deploys.
  • 9. Puma Based on Mongrel. Designed for concurrency. Uses real threads.
  • 10. Anatomy of a Web Request
  • 11. Link Clicked DOM Loaded Redirects Cache DNS TCP SSL Request App Response DOM Render First Byte Load
  • 15. Lazy Loading ๏ ORMs make it easy to access data. ๏ Easy access to data can create issues. ๏ Performance issues are hard to see in development mode. ๏ Look to production metrics to optimize and refactor.
  • 16. N+1 Query Creep # app/models/customer.rb class Customer < ActiveRecord::Base has_many :addresses end # app/models/address.rb class Address < ActiveRecord::Base belongs_to :customer end # app/controllers/customers_controller.rb class CustomersController < ApplicationController def index @customers = Customer.all end end # app/views/customers/index.html.erb <% @customers.each do |customer| %> <%= content_tag :h1, customer.name %> <% end %>
  • 17. N+1 Query Creep # app/views/customers/index.html.erb <% @customers.each do |customer| %> <%= content_tag :h1, customer.name %> <%= content_tag :h2, customer.addresses.first.city %> <% end %> If @customers has 100 records, you'll have 101 queries: SELECT "customers".* FROM "customers" SELECT "addresses".* FROM "addresses" WHERE "addresses"."customer_id" = 1 AND "addresses"."primary" = 't' LIMIT 1 SELECT "addresses".* FROM "addresses" WHERE "addresses"."customer_id" = 2 AND "addresses"."primary" = 't' LIMIT 1 SELECT "addresses".* FROM "addresses" WHERE "addresses"."customer_id" = 3 AND "addresses"."primary" = 't' LIMIT 1 ... ... SELECT "addresses".* FROM "addresses" WHERE "addresses"."customer_id" = 100 AND "addresses"."primary" = 't' LIMIT 1
  • 18. Eager Load Instead # app/controllers/customers_controller.rb class CustomersController < ApplicationController def index @customers = Customer.includes(:addresses).all end end If @customers has 100 records, now we only have 2 queries: SELECT "customers".* FROM "customers" SELECT "addresses".* FROM "addresses" WHERE "addresses"."customer_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100)
  • 20. Missing Indexes ๏ Searching a 1,000 row table with an index is 100x faster than searching without. ๏ Put indexes anywhere you might need to query; less is not more with indexes. ๏ Writing an index will lock your tables.
  • 22. Indexes are Easy # db/migrate/20120201040247_add_index_for_shop_id_on_orders.rb class AddIndexForShopIdOnOrders < ActiveRecord::Migration def change add_index :orders, :shop_id end end
  • 23. Cache All The Things
  • 24. Page Caching # app/controllers/products_controller.rb class ProductsController < ActionController caches_page :index def index @products = Products.all end def create expire_page :action => :index end end # /opt/nginx/conf/nginx.conf location / { gzip_static on; }
  • 25. Action Caching # app/controllers/products_controller.rb class ProductsController < ActionController before_filter :authenticate caches_action :index def index @products = Product.all end def create expire_action :action => :index end end
  • 26. Fragment Caching # app/views/products/index.html.erb <% Order.find_recent.each do |o| %> <%= o.buyer.name %> bought <%= o.product.name %> <% end %> <% cache(‘all_products’) do %> All available products: <% Product.all.each do |p| %> <%= link_to p.name, product_url(p) %> <% end %> <% end %> # app/controllers/products_controller.rb class ProductsController < ActionController def update expire_fragment(‘all_products’) end end
  • 27. Expiring Caches is Hard
  • 28. Russian Doll Caching # app/views/products/show.html.erb <% cache product do %> Product options: <%= render product.options %> <% end %> # app/views/options/_option.html.erb <% cache option do %> <%= option.name %> <%= option.description %> <% end %> # app/models/product.rb class Product < ActiveRecord::Base has_many :options end # app/models/option.rb class Option < ActiveRecord::Base belongs_to :product, touch: true end
  • 30. Procrastinate Reporting. Sending email. Processing images. Call external services. Building & Expiring Caches.
  • 31. Rescued by Resque class ReferralProcessor @queue = :referrals_queue def self.perform(schema_name, order_item_id) order_item = OrderItem.find(order_item_id) order = order_item.order user = order.user credit = AccountCredit.credit(order_item.unit_price, user, 'referral') credit.message = I18n.t('account_credits.predefined_messages.referral', :description => order_item.description) credit.save! debit = Transaction.account_debit(credit.amount, user) debit.order = order debit.save! order.issue_refund(return_to_inventory: false, gateway_first: true, cancel_items: false, cancel_certificates: false, amount: credit.amount, as: 'original', notify_user: false) if user.receives_mail_for?(:referral_purchase) SystemMailer.referral_refund(order_item, credit).deliver end end end
  • 32. Get in Line class ReferralObserver < ActiveRecord::Observer def after_create(referral) Resque.enqueue_in(1.day, ReferralProcessor, referral.item.id) end end # Get it started $ PIDFILE=./resque.pid BACKGROUND=yes QUEUE=referrals_queue rake environment resque:work
  • 33. It’s Free in Rails 4 Establishing basic Queue API. Implement push and pop. Easily swap out for Resque, Sidekiq, Delayed job.
  • 34. What’s One More Second?
  • 38. Monitor your applications. Performance is not set it and forget it. Database indexes are cheap, make more. Cache something, somewhere. Push work off to the background. Don’t neglect front-end performance.
  • 39. Q? 30-day free trial at newrelic.com/30