qconsp 2015 - dicas de performance para aplicações web

164
DICAS DE PERFORMANCE WEB Fabio Akita @AkitaOnRails

Upload: fabio-akita

Post on 15-Jul-2015

2.665 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: QConSP 2015 - Dicas de Performance para Aplicações Web

DICAS DE PERFORMANCEWEB

Fabio Akita @AkitaOnRails

Page 2: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 3: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 4: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 5: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 6: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 7: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 8: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 9: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 10: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 11: QConSP 2015 - Dicas de Performance para Aplicações Web

Back EndBrowser

Front EndRender

ExternalServices

Page 12: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 13: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 14: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 15: QConSP 2015 - Dicas de Performance para Aplicações Web

9 DICAS

Page 16: QConSP 2015 - Dicas de Performance para Aplicações Web

SLIDESHARE.NET/AKITAONRAILS

Page 17: QConSP 2015 - Dicas de Performance para Aplicações Web

MONITORING

Page 18: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 19: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 20: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 21: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 22: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 23: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 24: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 25: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 26: QConSP 2015 - Dicas de Performance para Aplicações Web

1.4 MILHOES DE VISITANTES UNICOS!!

Page 27: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 28: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 29: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 30: QConSP 2015 - Dicas de Performance para Aplicações Web

Ruby 2.1

Page 31: QConSP 2015 - Dicas de Performance para Aplicações Web

Ruby 2.2

Page 32: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 33: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 34: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 35: QConSP 2015 - Dicas de Performance para Aplicações Web

CACHING

Page 36: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 37: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 38: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 39: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 40: QConSP 2015 - Dicas de Performance para Aplicações Web

def  sitemap      sleep  3      @posts  =  Post.select([  :id,  :slug,  :updated_at,  :published_at  ]).published      respond_to  do  |format|          format.xml  {  render  layout:  false  }      end  end

Processing  by  ArchivesController#sitemap  as  XML      Rendered  archives/sitemap.xml.builder  (785.5ms)  Completed  200  OK  in  3879.4ms  (Views:  770.4ms  |  ActiveRecord:  18.7ms  |  Solr:  0.0ms)

Page 41: QConSP 2015 - Dicas de Performance para Aplicações Web

def  sitemap      @posts  =  cache('sitemap',  :expires_in  =>  12.hours)  {          sleep  3          Post.select([  :id,  :slug,  :updated_at,  :published_at  ]).published      }      respond_to  do  |format|          format.xml  {  render  layout:  false  }      end  end

Processing  by  ArchivesController#sitemap  as  XML      Rendered  archives/sitemap.xml.builder  (763.3ms)  Completed  200  OK  in  842.4ms  (Views:  754.2ms  |  ActiveRecord:  13.3ms  |  Solr:  0.0ms)

Page 42: QConSP 2015 - Dicas de Performance para Aplicações Web

def  sitemap      @posts  =  cache('sitemap',  :expires_in  =>  12.hours)  {          Post.select([  :id,  :slug,  :updated_at,  :published_at  ]).published      }      if  stale?(last_modified:  @posts.first.updated_at.utc,          etag:  "posts/#{@posts.count}-­‐#{@posts.first.updated_at.utc}")          respond_to  do  |format|              format.xml  {  render  layout:  false  }          end      end  end

Processing  by  ArchivesController#sitemap  as  XML  Completed  304  Not  Modified  in  6.2ms  (ActiveRecord:  1.7ms)

Page 43: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 44: QConSP 2015 - Dicas de Performance para Aplicações Web

2s!

Page 45: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 46: QConSP 2015 - Dicas de Performance para Aplicações Web

198ms!

Page 47: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 48: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 49: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 50: QConSP 2015 - Dicas de Performance para Aplicações Web

ASSET PIPELINE

Page 51: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 52: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 53: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 54: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 55: QConSP 2015 - Dicas de Performance para Aplicações Web

}}

Page 56: QConSP 2015 - Dicas de Performance para Aplicações Web

UPLOADS

Page 57: QConSP 2015 - Dicas de Performance para Aplicações Web

Browser

1s

Page 58: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s

Page 59: QConSP 2015 - Dicas de Performance para Aplicações Web

ImageMagickBackendBrowser

1s

Page 60: QConSP 2015 - Dicas de Performance para Aplicações Web

S3ImageMagickBackendBrowser

1s

Page 61: QConSP 2015 - Dicas de Performance para Aplicações Web

S3ImageMagickBackendBrowser

1s 2 segundos

Page 62: QConSP 2015 - Dicas de Performance para Aplicações Web

Browser

1s

Page 63: QConSP 2015 - Dicas de Performance para Aplicações Web

Browser

1s

S3

Page 64: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s

S3

Page 65: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s 200 ms

S3

Page 66: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s 200 ms

S3

ImageMagick

700 ms

Page 67: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 68: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 69: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  gem  'cloudinary'  gem  'attachinary'

Page 70: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  gem  'cloudinary'  gem  'attachinary'

#  config/cloudinary.yml  production:      cloud_name:  "sample"      api_key:  "874837483274837"      api_secret:  "a676b67565c6767a6767d6767f676fe1"

Page 71: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  gem  'cloudinary'  gem  'attachinary'

#  config/cloudinary.yml  production:      cloud_name:  "sample"      api_key:  "874837483274837"      api_secret:  "a676b67565c6767a6767d6767f676fe1"#  app/models/user.rb  

class  User  <  ActiveRecord::Base      attr_accessible  :name            has_attachment    :avatar      has_attachments  :photos,  maximum:  3  end

Page 72: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  gem  'cloudinary'  gem  'attachinary'

#  config/cloudinary.yml  production:      cloud_name:  "sample"      api_key:  "874837483274837"      api_secret:  "a676b67565c6767a6767d6767f676fe1"#  app/models/user.rb  

class  User  <  ActiveRecord::Base      attr_accessible  :name            has_attachment    :avatar      has_attachments  :photos,  maximum:  3  end

#  app/views/users/_form.html.slim  =  form_for(@user)  do  |user_form|          =  user_form.text_field(:name)          =  attachinary_file_field_tag  ‘user[avatar]',              @user,  :avatar          =  attachinary_file_field_tag  ‘user[photos]’,              @user,  :photos          =  user_form.submit("Save")

Page 73: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  gem  'cloudinary'  gem  'attachinary'

#  config/cloudinary.yml  production:      cloud_name:  "sample"      api_key:  "874837483274837"      api_secret:  "a676b67565c6767a6767d6767f676fe1"#  app/models/user.rb  

class  User  <  ActiveRecord::Base      attr_accessible  :name            has_attachment    :avatar      has_attachments  :photos,  maximum:  3  end

#  app/views/users/_form.html.slim  =  form_for(@user)  do  |user_form|          =  user_form.text_field(:name)          =  attachinary_file_field_tag  ‘user[avatar]',              @user,  :avatar          =  attachinary_file_field_tag  ‘user[photos]’,              @user,  :photos          =  user_form.submit("Save")

#  app/controllers/users_controller.rb  ...      def  create          @user  =  User.new(params[:user])          @user.save!      end

Page 74: QConSP 2015 - Dicas de Performance para Aplicações Web

#  app/views/users/show.html.slim  -­‐  if  user.avatar.present?      =  cl_image_tag(user.avatar.path,  width:  80,  height:  100,  crop:  :thumb,  gravity:  :face)      -­‐  user.photos.each  do  |photo|          =  cl_image_tag(photo.path,  size:  '70x50',  crop:  :fill,  radius:  20)

#  Gemfile  gem  'cloudinary'  gem  'attachinary'

#  config/cloudinary.yml  production:      cloud_name:  "sample"      api_key:  "874837483274837"      api_secret:  "a676b67565c6767a6767d6767f676fe1"#  app/models/user.rb  

class  User  <  ActiveRecord::Base      attr_accessible  :name            has_attachment    :avatar      has_attachments  :photos,  maximum:  3  end

#  app/views/users/_form.html.slim  =  form_for(@user)  do  |user_form|          =  user_form.text_field(:name)          =  attachinary_file_field_tag  ‘user[avatar]',              @user,  :avatar          =  attachinary_file_field_tag  ‘user[photos]’,              @user,  :photos          =  user_form.submit("Save")

#  app/controllers/users_controller.rb  ...      def  create          @user  =  User.new(params[:user])          @user.save!      end

Page 75: QConSP 2015 - Dicas de Performance para Aplicações Web

CDN

Page 76: QConSP 2015 - Dicas de Performance para Aplicações Web

AssetsRailsBrowser

1s 5 segundos

Page 77: QConSP 2015 - Dicas de Performance para Aplicações Web

Assets

RailsBrowser

1s 200 ms

4 segundos

Page 78: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 79: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 80: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 81: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

http://www.mydomain.com/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 82: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

http://www.mydomain.com/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 83: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

http://www.mydomain.com/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 84: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

http://www.mydomain.com/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 85: QConSP 2015 - Dicas de Performance para Aplicações Web

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

http://www.mydomain.com/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

Page 86: QConSP 2015 - Dicas de Performance para Aplicações Web

#  config/environments/production.rb  config.action_controller.asset_host  =  "d3vam04na8c92l.cloudfront.net"

<%=  stylesheet_link_tag        "application",  :media  =>  "all"  %>  <%=  javascript_include_tag  "application"  %>  <%=  image_tag("rails.png")  %>

<link  href="http://d3vam04na8c92l.cloudfront.net/stylesheets/application-­‐6502e5a88f02b90aeb32c2dd21ea37ab.css"  rel="stylesheet"  />

Page 87: QConSP 2015 - Dicas de Performance para Aplicações Web

DATABASE

Page 88: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 89: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 90: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 91: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  gem  "lol_dba",  group:  :development  

#  no  Terminal  bundle  install  bundle  exec  rake  db:find_indexes

Page 92: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 93: QConSP 2015 - Dicas de Performance para Aplicações Web

#  app/controllers/posts_controller.rb  def  index      @posts  =  Post.all  

   respond_to  do  |format|          format.html  #  index.html.erb          format.xml    {  render  :xml  =>  @posts  }      end  end

Page 94: QConSP 2015 - Dicas de Performance para Aplicações Web

#  app/controllers/posts_controller.rb  def  index      @posts  =  Post.all  

   respond_to  do  |format|          format.html  #  index.html.erb          format.xml    {  render  :xml  =>  @posts  }      end  end

<%  @posts.each  do  |post|  %>      <tr>          <td><%=  post.name  %></td>          <td><%=  post.comments.size  %></td>          <td><%=  link_to  'Show',  post  %></td>          <td><%=  link_to  'Edit',  edit_post_path(post)  %></td>          <td><%=  link_to  'Destroy',  post,  confirm:  'Are  you  sure?',  method:  :delete  %></td>      </tr>  <%  end  %>

Page 95: QConSP 2015 - Dicas de Performance para Aplicações Web

#  app/controllers/posts_controller.rb  def  index      @posts  =  Post.all  

   respond_to  do  |format|          format.html  #  index.html.erb          format.xml    {  render  :xml  =>  @posts  }      end  end

<%  @posts.each  do  |post|  %>      <tr>          <td><%=  post.name  %></td>          <td><%=  post.comments.size  %></td>          <td><%=  link_to  'Show',  post  %></td>          <td><%=  link_to  'Edit',  edit_post_path(post)  %></td>          <td><%=  link_to  'Destroy',  post,  confirm:  'Are  you  sure?',  method:  :delete  %></td>      </tr>  <%  end  %>

Started  GET  "/posts/"  for  192.168.47.2  at  2015-­‐03-­‐23  18:31:11  +0000  Cannot  render  console  from  192.168.47.2!  Allowed  networks:  127.0.0.1,  ::1,  127.0.0.0/127.255.255.255      ActiveRecord::SchemaMigration  Load  (0.1ms)    SELECT  "schema_migrations".*  FROM  "schema_migrations"  Processing  by  PostsController#index  as  HTML      Post  Load  (0.2ms)    SELECT  "posts".*  FROM  "posts"      Comment  Load  (0.2ms)    SELECT  "comments".*  FROM  "comments"  WHERE  "comments"."post_id"  =  ?    [["post_id",  1]]      Comment  Load  (0.1ms)    SELECT  "comments".*  FROM  "comments"  WHERE  "comments"."post_id"  =  ?    [["post_id",  2]]      Rendered  posts/index.html.erb  within  layouts/application  (25.3ms)  Completed  200  OK  in  679ms  (Views:  666.4ms  |  ActiveRecord:  1.0ms)

Page 96: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 97: QConSP 2015 - Dicas de Performance para Aplicações Web

#  app/controllers/posts_controller.rb  def  index      @posts  =  Post.all  

   respond_to  do  |format|          format.html  #  index.html.erb          format.xml    {  render  :xml  =>  @posts  }      end  end

<%  @posts.each  do  |post|  %>      <tr>          <td><%=  post.name  %></td>          <td><%=  post.comments.size  %></td>          <td><%=  link_to  'Show',  post  %></td>          <td><%=  link_to  'Edit',  edit_post_path(post)  %></td>          <td><%=  link_to  'Destroy',  post,  confirm:  'Are  you  sure?',  method:  :delete  %></td>      </tr>  <%  end  %>

Started  GET  "/posts/"  for  192.168.47.2  at  2015-­‐03-­‐23  18:31:11  +0000  Cannot  render  console  from  192.168.47.2!  Allowed  networks:  127.0.0.1,  ::1,  127.0.0.0/127.255.255.255      ActiveRecord::SchemaMigration  Load  (0.1ms)    SELECT  "schema_migrations".*  FROM  "schema_migrations"  Processing  by  PostsController#index  as  HTML      Post  Load  (0.2ms)    SELECT  "posts".*  FROM  "posts"      Comment  Load  (0.2ms)    SELECT  "comments".*  FROM  "comments"  WHERE  "comments"."post_id"  =  ?    [["post_id",  1]]      Comment  Load  (0.1ms)    SELECT  "comments".*  FROM  "comments"  WHERE  "comments"."post_id"  =  ?    [["post_id",  2]]      Rendered  posts/index.html.erb  within  layouts/application  (25.3ms)  Completed  200  OK  in  679ms  (Views:  666.4ms  |  ActiveRecord:  1.0ms)

Page 98: QConSP 2015 - Dicas de Performance para Aplicações Web

Started  GET  "/posts/"  for  192.168.47.2  at  2015-­‐03-­‐23  18:37:31  +0000  Cannot  render  console  from  192.168.47.2!  Allowed  networks:  127.0.0.1,  ::1,  127.0.0.0/127.255.255.255      ActiveRecord::SchemaMigration  Load  (0.1ms)    SELECT  "schema_migrations".*  FROM  "schema_migrations"  Processing  by  PostsController#index  as  HTML      Post  Load  (0.2ms)    SELECT  "posts".*  FROM  "posts"      Comment  Load  (0.2ms)    SELECT  "comments".*  FROM  "comments"  WHERE  "comments"."post_id"  IN  (1,  2)      Rendered  posts/index.html.erb  within  layouts/application  (25.8ms)  Completed  200  OK  in  109ms  (Views:  96.4ms  |  ActiveRecord:  0.9ms)

#  app/controllers/posts_controller.rb  def  index      @posts  =  Post.includes(:comments).all  

   respond_to  do  |format|          format.html  #  index.html.erb          format.xml    {  render  :xml  =>  @posts  }      end  end

<%  @posts.each  do  |post|  %>      <tr>          <td><%=  post.name  %></td>          <td><%=  post.comments.size  %></td>          <td><%=  link_to  'Show',  post  %></td>          <td><%=  link_to  'Edit',  edit_post_path(post)  %></td>          <td><%=  link_to  'Destroy',  post,  confirm:  'Are  you  sure?',  method:  :delete  %></td>      </tr>  <%  end  %>

Page 99: QConSP 2015 - Dicas de Performance para Aplicações Web

SEARCH

Page 100: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 101: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 102: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 103: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 104: QConSP 2015 - Dicas de Performance para Aplicações Web

ASYNC JOBS

Page 105: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 106: QConSP 2015 - Dicas de Performance para Aplicações Web

Browser

1s

Page 107: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s

Page 108: QConSP 2015 - Dicas de Performance para Aplicações Web

Tarefa DemoradaBackendBrowser

1s

Page 109: QConSP 2015 - Dicas de Performance para Aplicações Web

Tarefa DemoradaBackendBrowser

1s 4 segundos

Page 110: QConSP 2015 - Dicas de Performance para Aplicações Web

Browser

1s

Page 111: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s

Page 112: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s

Redis

Page 113: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s 200 ms

Redis

Page 114: QConSP 2015 - Dicas de Performance para Aplicações Web

BackendBrowser

1s 200 ms

Redis

Tarefa Demorada(Worker)

3.8 segundos

Page 115: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 116: QConSP 2015 - Dicas de Performance para Aplicações Web

class  VerySlowJob  <  ActiveJob::Base      queue_as  :default          def  perform(*args)          #  Tarefa  Demorada      end  end

Page 117: QConSP 2015 - Dicas de Performance para Aplicações Web

class  VerySlowJob  <  ActiveJob::Base      queue_as  :default          def  perform(*args)          #  Tarefa  Demorada      end  end

VerySlowJob.perform_later  record

Page 118: QConSP 2015 - Dicas de Performance para Aplicações Web

class  VerySlowJob  <  ActiveJob::Base      queue_as  :default          def  perform(*args)          #  Tarefa  Demorada      end  end

VerySlowJob.perform_later  record

VerySlowJob.set(wait_until:  Date.tomorrow.noon).perform_later(record)

Page 119: QConSP 2015 - Dicas de Performance para Aplicações Web

class  VerySlowJob  <  ActiveJob::Base      queue_as  :default          def  perform(*args)          #  Tarefa  Demorada      end  end

VerySlowJob.set(wait:  1.week).perform_later(record)

VerySlowJob.perform_later  record

VerySlowJob.set(wait_until:  Date.tomorrow.noon).perform_later(record)

Page 120: QConSP 2015 - Dicas de Performance para Aplicações Web

#  app/workers/report_job.rb  class  ReportJob  <  ActiveJob::Base      queue_as  :default          def  perform(email,  from_date  =  nil,  to_date  =  nil)          now  =  Time.zone.now          from_date  ||=  now  -­‐  1.year          to_date      ||=  now          file_path  =  ModelGigante.generate_excel(from_date,  to_date)          NotifyReportMailer.send(email,  file_path)      end  end

Page 121: QConSP 2015 - Dicas de Performance para Aplicações Web

#  app/controllers/reports_controller.rb  #  ...  def  create      ReportJob.perform_later(params[:email],          params[:from_date],  params[:to_date])      flash[:notice]  =  "Report  is  being  generated.          It  will  be  sent  to  your  email."      redirect_to  reports_path  end  #  ...

#  app/workers/report_job.rb  class  ReportJob  <  ActiveJob::Base      queue_as  :default          def  perform(email,  from_date  =  nil,  to_date  =  nil)          now  =  Time.zone.now          from_date  ||=  now  -­‐  1.year          to_date      ||=  now          file_path  =  ModelGigante.generate_excel(from_date,  to_date)          NotifyReportMailer.send(email,  file_path)      end  end

Page 122: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 123: QConSP 2015 - Dicas de Performance para Aplicações Web

ASYNC MESSAGES

Page 124: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 125: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 126: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 127: QConSP 2015 - Dicas de Performance para Aplicações Web

http://blog.tryneighborly.com/amazon-sns-for-apns-on-rails/

Page 128: QConSP 2015 - Dicas de Performance para Aplicações Web

<!-­‐-­‐  chat.html  -­‐-­‐>  <script  src="//js.pusher.com/2.2/pusher.min.js"></script>  <script>  $(function()  {          var  pusher  =  new  Pusher('YOUR_APP_KEY');          var  channel  =  pusher.subscribe('my-­‐app-­‐chat');          channel.bind('new-­‐message',  function(data)  {                  $('#chat-­‐box').append(data.message);          });  })  </script>

Page 129: QConSP 2015 - Dicas de Performance para Aplicações Web

<!-­‐-­‐  chat.html  -­‐-­‐>  <script  src="//js.pusher.com/2.2/pusher.min.js"></script>  <script>  $(function()  {          var  pusher  =  new  Pusher('YOUR_APP_KEY');          var  channel  =  pusher.subscribe('my-­‐app-­‐chat');          channel.bind('new-­‐message',  function(data)  {                  $('#chat-­‐box').append(data.message);          });  })  </script>

#  config/initializer/pusher.rb  Pusher.app_id  =  ENV['PUSHER_APP_ID']  Pusher.key        =  ENV['PUSHER_APP_KEY']  Pusher.secret  =  ENV['PUSHER_APP_SECRET']  

Page 130: QConSP 2015 - Dicas de Performance para Aplicações Web

<!-­‐-­‐  chat.html  -­‐-­‐>  <script  src="//js.pusher.com/2.2/pusher.min.js"></script>  <script>  $(function()  {          var  pusher  =  new  Pusher('YOUR_APP_KEY');          var  channel  =  pusher.subscribe('my-­‐app-­‐chat');          channel.bind('new-­‐message',  function(data)  {                  $('#chat-­‐box').append(data.message);          });  })  </script>

#  config/initializer/pusher.rb  Pusher.app_id  =  ENV['PUSHER_APP_ID']  Pusher.key        =  ENV['PUSHER_APP_KEY']  Pusher.secret  =  ENV['PUSHER_APP_SECRET']  

#  app/workers/new_message_worker.rb  require  'pusher'  class  NewMessageWorker      include  Sidekiq::Worker            def  perform(message_id)          @message  =  Message.find(message_id)          Pusher.trigger('my-­‐app-­‐chat',  'new-­‐message',  {:message  =>  @message})      end  end

Page 131: QConSP 2015 - Dicas de Performance para Aplicações Web

<!-­‐-­‐  chat.html  -­‐-­‐>  <script  src="//js.pusher.com/2.2/pusher.min.js"></script>  <script>  $(function()  {          var  pusher  =  new  Pusher('YOUR_APP_KEY');          var  channel  =  pusher.subscribe('my-­‐app-­‐chat');          channel.bind('new-­‐message',  function(data)  {                  $('#chat-­‐box').append(data.message);          });  })  </script>

#  app/controllers/messages_controller.rb  #  ...  def  create      @message  =  Message.new(params[:message])      if  @messsage.save          NewMessageWorker.perform_async(@message.id)          #  ...  end  #  ...

#  config/initializer/pusher.rb  Pusher.app_id  =  ENV['PUSHER_APP_ID']  Pusher.key        =  ENV['PUSHER_APP_KEY']  Pusher.secret  =  ENV['PUSHER_APP_SECRET']  

#  app/workers/new_message_worker.rb  require  'pusher'  class  NewMessageWorker      include  Sidekiq::Worker            def  perform(message_id)          @message  =  Message.find(message_id)          Pusher.trigger('my-­‐app-­‐chat',  'new-­‐message',  {:message  =>  @message})      end  end

Page 132: QConSP 2015 - Dicas de Performance para Aplicações Web

TUNING RUBY

Page 133: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 134: QConSP 2015 - Dicas de Performance para Aplicações Web

http://www.infoq.com/news/2014/12/ruby-2.2.0-released

Page 135: QConSP 2015 - Dicas de Performance para Aplicações Web

http://www.infoq.com/news/2014/12/ruby-2.2.0-released

Page 136: QConSP 2015 - Dicas de Performance para Aplicações Web

• Mark and Sweep GC (1.8+)

http://www.infoq.com/news/2014/12/ruby-2.2.0-released

Page 137: QConSP 2015 - Dicas de Performance para Aplicações Web

• Mark and Sweep GC (1.8+)

• Bitmap Marking GC (1.9.3+)

http://www.infoq.com/news/2014/12/ruby-2.2.0-released

Page 138: QConSP 2015 - Dicas de Performance para Aplicações Web

• Mark and Sweep GC (1.8+)

• Bitmap Marking GC (1.9.3+)

• Lazy Sweep GC (2.0.0+)

http://www.infoq.com/news/2014/12/ruby-2.2.0-released

Page 139: QConSP 2015 - Dicas de Performance para Aplicações Web

• Mark and Sweep GC (1.8+)

• Bitmap Marking GC (1.9.3+)

• Lazy Sweep GC (2.0.0+)

• Restricted Generational GC (RGenGC 2.1.0+)

http://www.infoq.com/news/2014/12/ruby-2.2.0-released

Page 140: QConSP 2015 - Dicas de Performance para Aplicações Web

• Mark and Sweep GC (1.8+)

• Bitmap Marking GC (1.9.3+)

• Lazy Sweep GC (2.0.0+)

• Restricted Generational GC (RGenGC 2.1.0+)

• Restricted Incremental GC (RIncGC 2.2.0+)

http://www.infoq.com/news/2014/12/ruby-2.2.0-released

Page 141: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 142: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 143: QConSP 2015 - Dicas de Performance para Aplicações Web

TRADE-OFF:+ GC OU + RAM

Page 144: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 145: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  source  'https://rubygems.org'  

ruby  "2.2.1"  

#  performance  tuning  gem  'escape_utils'  gem  'fast_blank'  gem  'oj'  gem  'oj_mimic_json'

http://marianposaceanu.com/articles/improve-rails-performance-by-adding-a-few-gems

Page 146: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 147: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  source  'https://rubygems.org'  

if  ENV['RAILS_ENV']  ==  'production'      ruby  '1.9.3',  :engine  =>  'jruby',  :engine_version  =>  '1.7.18'  else      ruby  '2.2.1'  end  

gem  'rails',  '4.2.0'  gem  'rails-­‐api'  gem  'srt'  gem  'pg',  platforms:  'mri'  gem  'activerecord-­‐jdbcpostgresql-­‐adapter',  platforms:  'jruby'  

gem  'sidekiq'  gem  'dalli'  gem  'puma'  gem  'rack-­‐cache'  gem  'rack-­‐cors',  require:  'rack/cors'  gem  'rails_12factor'  gem  'newrelic_rpm'

Page 148: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  source  'https://rubygems.org'  

if  ENV['RAILS_ENV']  ==  'production'      ruby  '1.9.3',  :engine  =>  'jruby',  :engine_version  =>  '1.7.18'  else      ruby  '2.2.1'  end  

gem  'rails',  '4.2.0'  gem  'rails-­‐api'  gem  'srt'  gem  'pg',  platforms:  'mri'  gem  'activerecord-­‐jdbcpostgresql-­‐adapter',  platforms:  'jruby'  

gem  'sidekiq'  gem  'dalli'  gem  'puma'  gem  'rack-­‐cache'  gem  'rack-­‐cors',  require:  'rack/cors'  gem  'rails_12factor'  gem  'newrelic_rpm'

Page 149: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  source  'https://rubygems.org'  

if  ENV['RAILS_ENV']  ==  'production'      ruby  '1.9.3',  :engine  =>  'jruby',  :engine_version  =>  '1.7.18'  else      ruby  '2.2.1'  end  

gem  'rails',  '4.2.0'  gem  'rails-­‐api'  gem  'srt'  gem  'pg',  platforms:  'mri'  gem  'activerecord-­‐jdbcpostgresql-­‐adapter',  platforms:  'jruby'  

gem  'sidekiq'  gem  'dalli'  gem  'puma'  gem  'rack-­‐cache'  gem  'rack-­‐cors',  require:  'rack/cors'  gem  'rails_12factor'  gem  'newrelic_rpm'

Page 150: QConSP 2015 - Dicas de Performance para Aplicações Web

#  Gemfile  source  'https://rubygems.org'  

if  ENV['RAILS_ENV']  ==  'production'      ruby  '1.9.3',  :engine  =>  'jruby',  :engine_version  =>  '1.7.18'  else      ruby  '2.2.1'  end  

gem  'rails',  '4.2.0'  gem  'rails-­‐api'  gem  'srt'  gem  'pg',  platforms:  'mri'  gem  'activerecord-­‐jdbcpostgresql-­‐adapter',  platforms:  'jruby'  

gem  'sidekiq'  gem  'dalli'  gem  'puma'  gem  'rack-­‐cache'  gem  'rack-­‐cors',  require:  'rack/cors'  gem  'rails_12factor'  gem  'newrelic_rpm'

Page 151: QConSP 2015 - Dicas de Performance para Aplicações Web

9 DICAS

Page 152: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 153: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Page 154: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Page 155: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Page 156: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Database PostgreSQL

Page 157: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Database PostgreSQL

Search Elastic

Page 158: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Database PostgreSQL

Search Elastic

Async Jobs Sidekiq, Redis

Page 159: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Database PostgreSQL

Search Elastic

Async Jobs Sidekiq, Redis

Async Messages pusher.com

Page 160: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Database PostgreSQL

Search Elastic

Async Jobs Sidekiq, Redis

Async Messages pusher.com

Auto scale HireFire, AdeptScale

Page 161: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Database PostgreSQL

Search Elastic

Async Jobs Sidekiq, Redis

Async Messages pusher.com

Auto scale HireFire, AdeptScale

Rubies Ruby 2.2.1, JRuby

Page 162: QConSP 2015 - Dicas de Performance para Aplicações Web

Monitoring New Relic

Caching Memcache, ETAG

Assets CloudFlare, Cloudinary

Database PostgreSQL

Search Elastic

Async Jobs Sidekiq, Redis

Async Messages pusher.com

Auto scale HireFire, AdeptScale

Rubies Ruby 2.2.1, JRuby

Deployment Heroku

Page 163: QConSP 2015 - Dicas de Performance para Aplicações Web
Page 164: QConSP 2015 - Dicas de Performance para Aplicações Web

OBRIGADOslideshare.net/akitaonrails