Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RubyChina 2012 - Ten slow things you don't know

RubyChina 2012 - Ten slow things you don't know

RubyChina 2012

Yi-Ting Cheng

November 18, 2012
Tweet

More Decks by Yi-Ting Cheng

Other Decks in Technology

Transcript

  1. 最佳實踐如何變成了最慢實踐
    ⼗十個你不知道會導致效能低落的設計
    12年11月18⽇日星期⽇日

    View Slide

  2. Me
    • http://blog.xdite.net
    • Rails Developer ( 2007~ )
    • ROCO Inc. Founder
    • Facebook World Hack 世界⾸首獎
    12年11月18⽇日星期⽇日

    View Slide

  3. why this topic?
    12年11月18⽇日星期⽇日

    View Slide

  4. We follow
    • Convention over configuration
    • Best Practices
    • Default
    • Instinct!!!
    12年11月18⽇日星期⽇日

    View Slide

  5. 效能越來越差
    12年11月18⽇日星期⽇日

    View Slide

  6. New Relic 抓不出來
    12年11月18⽇日星期⽇日

    View Slide

  7. 抓不到的地⽅方
    • Deployment
    • Asset Compiling
    • Loading Environment
    • ActiveRecord (MySQL) convention
    • View
    12年11月18⽇日星期⽇日

    View Slide

  8. Deployment
    12年11月18⽇日星期⽇日

    View Slide

  9. Bundler
    desc "Run bundle install"
    task :install_bundle_gems do
    run "cd #{deploy_to}/current; RAILS_ENV=#{rails_env} bundle install"
    end
    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  10. Bundler
    load ‘bundler/capistrano’
    bundle install --gemfile /home/apps/project/releases/20121114191908/Gemfile --path /home/apps/d4dpr/shared/
    bundle --deployment --quiet --without development test
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  11. Deploy with Asset precompile
    rake RAILS_ENV=production assets:precompile
    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  12. Deploy with Asset precompile
    load 'deploy/assets'
    rake RAILS_ENV=production RAILS_GROUPS=assets
    assets:precompile
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  13. Deploy with Asset precompile
    set :assets_dependencies, %w(app/assets lib/assets vendor/assets Gemfile.lock config/routes.rb)
    namespace :deploy do
    namespace :assets do
    desc <Run the asset precompilation rake task. You can specify the full path \
    to the rake executable by setting the rake variable. You can also \
    specify additional environment variables to pass to rake via the \
    asset_env variable. The defaults are:
    set :rake, "rake"
    set :rails_env, "production"
    set :asset_env, "RAILS_GROUPS=assets"
    set :assets_dependencies, fetch(:assets_dependencies) + %w(config/locales/js)
    DESC
    task :precompile, :roles => :web, :except => { :no_release => true } do
    from = source.next_revision(current_revision)
    if capture("cd #{latest_release} && #{source.local.log(from)} #{assets_dependencies.join ' '} | wc -l").to_i > 0
    run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}
    else
    logger.info "Skipping asset pre-compilation because there were no asset changes"
    end
    end
    end
    end
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  14. Deploy with Asset precompile
    https://github.com/ndbroadbent/turbo-sprockets-rails3
    only recompiling changed assets
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  15. Asset Pipeline
    12年11月18⽇日星期⽇日

    View Slide

  16. Asset Pipeline(require_tree)
    • good for split controller specific logic
    • posts.js.coffee
    12年11月18⽇日星期⽇日

    View Slide

  17. Asset Pipeline(require_tree)
    • require_tree
    • users.js.coffee
    • posts.js.coffee
    • products.js.coffee
    • .....
    Default & Slow
    12年11月18⽇日星期⽇日

    View Slide

  18. Asset Pipeline(require_tree)
    # posts.js.coffee
    # Place all the behaviors and hooks related to the matching controller here.
    # All this logic will automatically be available in application.js.
    # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
    empty_assets still cost compile time
    ~250ms
    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  19. Asset Pipeline(require_tree)
    • remove *.js.coffee (empty)
    • only require what you need
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  20. Asset Pipeline(@import)
    • @import is awesome
    • Web have “compass”
    12年11月18⽇日星期⽇日

    View Slide

  21. Asset Pipeline(@import)
    • import “compass”
    • @import "compass/utilities";
    • @import "utilities/color";
    • @import "utilities/general";
    • @import "utilities/sprites";
    • @import "utilities/tables";
    • @import "compass/typography";
    • @import "compass/css3";
    recursive @import
    Slow
    12年11月18⽇日星期⽇日

    View Slide

  22. Asset Pipeline(@import)
    • Only @import specific SCSS
    @import "compass/typography/links/link-colors";
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  23. Loading Environment
    12年11月18⽇日星期⽇日

    View Slide

  24. Bundler Group matters
    • import all gems without grouping
    gem "capistrano"
    gem "capistrano-ext"
    gem "cape"
    gem "magic_encoding"
    gem "annotate"
    gem “rspec”
    gem “capybara”
    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  25. Bundler Group matters
    • group by environment
    group :development do
    gem "capistrano"
    gem "capistrano-ext"
    gem "cape"
    gem "magic_encoding"
    gem "annotate"
    end
    group :test do
    gem “rspec”
    gem “capybara”
    end
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  26. ActiveRecord with MySQL
    12年11月18⽇日星期⽇日

    View Slide

  27. Order by String
    • state machine
    • published
    • draft
    • rejected
    12年11月18⽇日星期⽇日

    View Slide

  28. Order by String
    # current_state :string(255)
    add_column :posts,: current_state, :string
    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  29. Order by String
    add_column :posts,: current_state, :string , :limit => 11
    Solution
    Optimal index size for variable text in MySQL
    http://www.xarg.org/2012/07/optimal-index-size-
    for-variable-text-in-mysql/
    12年11月18⽇日星期⽇日

    View Slide

  30. map(&:id)

    ( SELECT * from `posts` )
    [1,3,5,8,13,21]
    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  31. map(&:id)

    ( SELECT id from `posts` )
    [1,3,5,8,13,21]
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  32. timestamp
    create_table :invoices do |t|
    t.integer :user_id
    t.datetime :paid_at
    t.timestamps
    end
    scope :recent_paid, order(“paid_at DESC”)
    Default & Slow Slow Slow
    12年11月18⽇日星期⽇日

    View Slide

  33. timestamp
    add_column :invoices, :paid_at, :integer
    Time.to_i DateTime.strptime("1318996912",'%s')
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  34. View
    12年11月18⽇日星期⽇日

    View Slide

  35. Logic in View
    • ERB with eval

    admin panel

    user panel

    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  36. Logic in View
    • ERB with eval

    Solution
    12年11月18⽇日星期⽇日

    View Slide

  37. Query in View/Helper
    • Query in view doesn’t have cache

    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  38. Query in View/Helper
    class Post < ActiveRecord::Base
    def author_name
    user.try(:name)
    end
    end
    Solution

    12年11月18⽇日星期⽇日

    View Slide

  39. for each

    ”>



    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  40. for each
    “posts”) do |post| %>


    Solution
    12年11月18⽇日星期⽇日

    View Slide

  41. complex link_to

    ”>



    Wrong & Slow
    12年11月18⽇日星期⽇日

    View Slide

  42. complex link_to
    content_tag(:i, :class => “icon icon-user”) + content_tag(:span, current_user. name)
    end %>
    Solution
    12年11月18⽇日星期⽇日

    View Slide

  43. Conclusion
    12年11月18⽇日星期⽇日

    View Slide

  44. use convention carefully
    12年11月18⽇日星期⽇日

    View Slide

  45. dig deep
    12年11月18⽇日星期⽇日

    View Slide

  46. back to basic
    12年11月18⽇日星期⽇日

    View Slide

  47. Thanks for listening
    12年11月18⽇日星期⽇日

    View Slide

  48. Q&A
    12年11月18⽇日星期⽇日

    View Slide