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

High Performance Rails (long edition)

High Performance Rails (long edition)

Which I talked at Rubykaigi 2013 is: https://speakerdeck.com/mirakui/high-performance-rails

Issei Naruta

May 31, 2013
Tweet

More Decks by Issei Naruta

Other Decks in Programming

Transcript

  1. )JHI
    1FSGPSNBODF
    3BJMT
    Issei Naruta
    RubyKaigi 2013
    (long edition)

    View full-size slide

  2. *TTFJ/BSVUB
    VP of DevOps at COOKPAD Inc.
    @mirakui
    Image delivering &&
    site performance improvement

    View full-size slide

  3. “Speed up Rails”

    View full-size slide

  4. COOKPAD is Japan’s
    top recipe site
    allowing visitors to
    upload and search
    through original, user-
    created recipes.
    20 million UU/month
    1.38 million recipes
    *Jan 2013

    View full-size slide

  5. $00,1"%
    • AWS
    • Rails 3.2
    • Ruby 2.0.0

    View full-size slide

  6. 4J[FPG
    0VS3BJMT"QQ
    • 1003 models
    • 236 controllers
    • 2871 view templates
    • 1978 lines in routes.rb
    • 3383 assets in manifest.yml
    *26 May 2013

    View full-size slide

  7. 8IBUJTUIF
    lSFTQPOTFUJNFz

    View full-size slide

  8. Started GET "/articles/1" ...
    :
    Article Load (0.1ms) SELECT articles.* FROM ...
    :
    Rendered articles/show.html.erb within layouts/application (0.7ms)
    Completed 200 OK in 100ms (Views: 70.1ms | ActiveRecord: 10.0ms)
    3FTQPOTFUJNFJO
    SBJMTMPH

    View full-size slide

  9. 3FTQPOTFUJNFJO
    SFTQPOTFIFBEFS
    X-Runtime: 0.123456

    View full-size slide

  10. routing
    before_filter
    after_filter
    rendering
    action
    Rails
    Rack
    "Completed" time
    X-Runtime
    )5513FRVFTU
    )5513FTQPOTF

    View full-size slide

  11. http://www.techempower.com/benchmarks/
    Rails
    (slow)
    Servlet
    (fast)
    8FC'SBNFXPSL#FODINBSLT

    View full-size slide

  12. .BKPSQSFNJTFPG
    IJHIQFSGPSNBODF
    3BJMTBQQT

    View full-size slide

  13. %PO`UQSPDFTT
    SVCZDPEF
    JGQPTTJCMF

    View full-size slide

  14. /HJOY
    6OJDPSO
    QSPYZ
    CVGGFSJOH
    3BJMT

    View full-size slide

  15. /HJOY
    6OJDPSO
    serve
    static files

    View full-size slide

  16. /HJOY
    6OJDPSO
    7BSOJTI
    "QBDIF
    TUBUJDpMFT
    QBHFDBDIJOH
    QSPYZ
    CVGGFSJOH
    3BJMT

    View full-size slide

  17. #SPXTFSTJEF
    $BDIJOH

    View full-size slide

  18. #SPXTFSTJEF
    $BDIJOH

    View full-size slide

  19. 6TJOHCSPXTFSTJEFDBDIJOH

    View full-size slide

  20. /FWFSVTFCSPXTFSTJEFDBDIJOH

    View full-size slide

  21. $POEJUJPOBM(&5

    View full-size slide

  22. 1st request
    2nd request

    View full-size slide

  23. GSFTI@XIFO
    • Set ETag and Last-Modified to
    response header
    • Return “304 Not Modified” if;
    •ETag == If-None-Match
    • Last-Modified <= If-Modified-Since
    • Skip rendering if 304 (fast!)

    View full-size slide

  24. FUBH\^
    3BJMT

    ETag is made of

    View full-size slide

  25. 0VSSVCZIJTUPSZ
    • Sep 2012
    • REE (Ruby Enterprise Edition) 1.8.7
    • Feb 2013
    • MRI 1.9.3
    • Apr 2013
    • MRI 2.0.0

    View full-size slide

  26. 8IBU`T3&&
    • MRI 1.8.7 + “MBARI patch”
    • “100% compatible with MRI 1.8.7”
    • Copy-on-Write Friendly GC
    • tcmalloc

    View full-size slide

  27. REE 1.8.7 MRI 1.9.3 MRI 2.0.0
    3FTQPOTFUJNF
    CZSVCZWFSTJPOT
    -100ms
    -20ms

    View full-size slide

  28. #FODINBSLT
    JOUIJTQSFTFOUBUJPOBSF
    3VCZ
    3BJMTSD

    View full-size slide

  29. 1FSGPSNBODF
    #PUUMFOFDLT
    JO3BJMT

    View full-size slide

  30. 0% 20% 40% 60% 80% 100%
    SQL Ruby
    3FTQPOTFUJNF
    CSFBLEPXO
    SFDJQFTIPX DPPLQBEDPN

    View full-size slide

  31. 4MPXTUVGG
    *FYQFSJFODFE
    • ActiveRecord objects creation
    • Resolving routes

    View full-size slide

  32. "DUJWF3FDPSE`T
    PWFSIFBE
    "SUJDMFMBTU
    UP@B
    "SUJDMF-PBE NT
    4&-&$5ABSUJDMFTA'30.

    View full-size slide

  33. "DUJWF3FDPSE`T
    PWFSIFBE
    #FODINBSLNT\"SUJDMFMBTU
    UP@B^
    "SUJDMF-PBE NT
    4&-&$5ABSUJDMFTA'30.

    The query is fast enough but
    creating 100 AR objects is slow

    View full-size slide

  34. 3FTPMWJOHSPVUFT
    • Fat routes slow down url_for
    • e.g. link_to helper

    View full-size slide

  35. 4J[FPG
    0VS3BJMT"QQ
    • 1003 models
    • 236 controllers
    • 2871 view templates
    • 1978 lines in routes.rb
    • 3383 assets in manifest.yml
    *26 May 2013

    View full-size slide

  36. MJOL@UPIFMMP IFMMP@JOEFY@VSM
    MJOL@UPbIFMMP` DPOUSPMMFSbIFMMP` BDUJPObJOEFY`
    8IJDIJTGBTUFS

    View full-size slide

  37. DPOpHSPVUFTSC
    HFUbIFMMPJOEFY` UPbIFMMPJOEFY`
    UJNFTEPcJc
    HFUlIFMMP\J^z UPbIFMMPJOEFY`
    FOE
    .BLFGBUSPVUFT

    View full-size slide

  38. MJOL@UPIFMMP IFMMP@JOEFY@VSM
    NT
    MJOL@UPbIFMMP` DPOUSPMMFSbIFMMP` BDUJPObJOEFY`
    NT
    3FTVMU

    View full-size slide

  39. 4MPXSBDL
    NJEEMFXBSF
    w3BDL$BDIF
    • Caches response with Rails.cache
    • Default in Rails 3.2
    • Not default in Rails 4

    View full-size slide

  40. 'SBHNFOU$BDIF

    View full-size slide

  41. DBDIFEP
    USFOE@LFZXPSET
    FOE

    View full-size slide

  42. DBDIFEP
    controller
    action
    cache digest (Rails4)
    views/localhost:3000/hello/cache_test/3e9258928c27f4ffc5135520c3a976c5
    %FGBVMUDBDIFLFZ

    View full-size slide

  43. DBDIFGSBHNFOUbLFZ`EP
    views/localhost:3000/hello/cache_test?fragment=key1
    /3e9258928c27f4ffc5135520c3a976c5
    fragment key
    'SBHNFOUDBDIFLFZ

    View full-size slide

  44. DBDIFbLFZ`EP
    views/key1/116839051556390fb4d5b25362cfe6eb
    global key
    (MPCBMDBDIFLFZ

    View full-size slide

  45. DBDIF!BSUJDMFEP
    table name
    @article.cache_key
    (id, updated_at)
    views/articles/1-20130527190532189241000
    /116839051556390fb4d5b25362cfe6eb
    "3DBDIFLFZ

    View full-size slide

  46. $BDIF%JHFTUT
    BLBl3VTTJBOEPMMDBDIJOHz

    View full-size slide

  47. projects documents comments
    1 * 1 *
    has_many :documents has_many :comments
    belongs_to :document
    id
    updated_at
    id
    project_id
    updated_at
    id
    document_id
    updated_at
    belongs_to :documents

    View full-size slide

  48. projects/show.html.erb
    _document.html.erb
    _comment.html.erb
    DBDIFQSPKFDUEP
    DBDIFEPDVNFOUEP
    DBDIFDPNNFOUEP

    View full-size slide

  49. comment.update!

    View full-size slide

  50. projects/show.html.erb
    _document.html.erb
    _comment.html.erb
    DBDIFQSPKFDUEP
    DBDIFEPDVNFOUEP
    DBDIFDPNNFOUEP
    still old...
    3BJMT
    ʜʜ
    LFZOPUDIBOHFE
    ʜʜ

    View full-size slide

  51. projects documents comments
    1 * 1 *
    has_many :documents has_many :comments
    belongs_to :document,
    touch: true
    id
    updated_at
    id
    project_id
    updated_at
    id
    document_id
    updated_at
    belongs_to :documents,
    touch: true
    update

    View full-size slide

  52. projects/show.html.erb
    _document.html.erb
    _comment.html.erb
    DBDIFQSPKFDUEP
    DBDIFEPDVNFOUEP
    DBDIFDPNNFOUEP
    updated
    3BJMT8BZ
    LFZDIBOHFE
    LFZDIFOHFE
    LFZDIBOHFE

    View full-size slide

  53. projects/show.html.erb
    _document.html.erb
    _comment.html.erb
    DBDIFQSPKFDUEP
    DBDIFEPDVNFOUEP
    DBDIFDPNNFOUEP
    updated
    3BJMT8BZ
    LFZDIBOHFE
    .PEJGZpMF
    LFZDIBOHFE

    View full-size slide

  54. made of [id, updated_at]
    MD5 of the template file itself
    and all of its dependencies
    views/documents/1-20130527190532189241000
    /116839051556390fb4d5b25362cfe6eb

    View full-size slide

  55. caches_action :show,
    if: -> { !current_user.staff? },
    cache_path: -> { custom_cache_path },
    expires_in: 1.hour

    View full-size slide

  56. expires_in
    Sweeper
    expires_in
    expires_in
    expires_in
    Sweeper
    Sweeper
    Sweeper
    Sweeper
    Sweeper
    Sweeper
    expires_in
    expires_in
    expires_in
    Sweeper

    View full-size slide

  57. Action Caching is not Rails 4 Way
    Use Russian-doll Caching

    View full-size slide

  58. action cache
    page cache
    sweeper
    actionpack-action_caching
    actionpack-page_caching
    rails-observers
    &YUSBDUFEBTHFNT
    GPS3BJMT
    3BJMT

    View full-size slide

  59. 5FNQMBUF
    &OHJOFT

    View full-size slide

  60. FSC
    IBNM
    TMJN
    )PX3BJMTSFOEFS
    UFNQMBUFT

    View full-size slide

  61. FSC
    IBNM
    TMJN
    3VCZ
    )PX3BJMTSFOEFS
    UFNQMBUFT
    "DUJPO7JFX5FNQMBUFDPNQJMF
    BUpSTUUJNFPG
    SFOEFSJOHFBDIUFNQMBUFT

    View full-size slide

  62. SFOEFSbFSC@UFTU`
    @BQQ@WJFXT@IFMMP@FSC@UFTU@IUNM@FSC@@@
    Calls

    View full-size slide

  63. Compiling time is not
    critical matter for Rails apps,
    but rendering time is.

    View full-size slide

  64. #FODINBSL
    UJNFTEP
    SFOEFS@UP@TUSJOH
    FOE
    ERB (erubis)
    Haml
    Slim

    View full-size slide

  65. 3FOEFSJOH5JNF
    ERB Haml Slim
    1,032.49 ms
    1,866.02 ms
    1,689.26 ms

    View full-size slide

  66. 6OJDPSOXJUI
    ($EJTBCMF

    View full-size slide

  67. )5513FRVFTUT
    time

    View full-size slide

  68. 6OJDPSO%FGBVMU
    GC

    View full-size slide

  69. ($EJTBCMF
    GC.start
    GC.disable GC.disable

    View full-size slide

  70. # unicorn config
    after_fork do |server, worker|
    GC.disable
    end
    # config.ru
    require “unicorn/oob_gc”
    use Unicorn::OobGC, 10
    Run GC each 10 requests

    View full-size slide

  71. # config.ru
    # Unicorn self-process killer
    require 'unicorn/worker_killer'
    # Max requests per worker
    use Unicorn::WorkerKiller::MaxRequests, 3072, 4096
    # Max memory size (RSS) per worker
    use Unicorn::WorkerKiller::Oom, (192*(1024**2)),
    (256*(1024**2))
    VOJDPSOXPSLFSLJMMFS
    IUUQTHJUIVCDPNL[LVOJDPSOXPSLFSLJMMFS

    View full-size slide

  72. SVCZQSPG
    • Call-tree is too complex to profile
    Rails apps

    View full-size slide

  73. "DUJWF4VQQPSU#FODINBSLBCMF
    3BJMTPSMBUFS

    <% benchmark "Process data files" do %>
    <%= expensive_files_operation %>
    <% end %>
    # production.log
    Process data files (123.45ms)

    View full-size slide

  74. 'JHIUJOHBHBJOTU
    TMPXRVFSJFT

    View full-size slide

  75. "SQSPYZ
    IUUQTHJUIVCDPNDPPLQBEBSQSPYZ
    "DUJWF3FDPSE
    %#"EBQUFS
    SELECT * FROM ...
    Query

    View full-size slide

  76. "SQSPYZ
    IUUQTHJUIVCDPNDPPLQBEBSQSPYZ
    "DUJWF3FDPSE
    %#"EBQUFS
    1SPYZ
    1SPYZ
    logging
    rewrite
    query

    View full-size slide

  77. "SQSPYZFYBNQMF

    View full-size slide

  78. "SQSPYZFYBNQMF
    "DUJWF3FDPSE
    %#"EBQUFS
    SELECT * FROM ...
    $PNNFOU"EEFS
    SELECT * FROM ... /*this_is_comment*/

    View full-size slide

  79. "DUJWF3FDPSE
    %#"EBQUFS
    "SQSPYZ qVFOUE .POHP%#
    -PHHJOHTMPXRVFSJFT
    VTJOH"SQSPYZ

    View full-size slide

  80. 5SBEFPGG
    JOQFSGPSNBODFUVOJOH

    View full-size slide

  81. %FWFMPQFST
    6TFST 4FSWFST

    View full-size slide

  82. 8F`SFIJSJOH
    http://info.cookpad.com/jobs/
    [en, ja]

    View full-size slide

  83. 5JNFUPIBDL HVZT
    http://info.cookpad.com/24contest4
    http://info.cookpad.com/24contest4_en
    24-hour hack-a-thon
    June 15 - 16
    [en]
    [ja]

    View full-size slide

  84. 5IBOLZPVGPS
    MJTUFOJOH

    View full-size slide