Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

“Speed up Rails”

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

NT

Slide 9

Slide 9 text

8IBUJTUIF lSFTQPOTFUJNFz

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

3FTQPOTFUJNFJO SFTQPOTFIFBEFS X-Runtime: 0.123456

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

*T3BJMT4MPX

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

.BKPSQSFNJTFPG IJHIQFSGPSNBODF 3BJMTBQQT

Slide 16

Slide 16 text

%PO`UQSPDFTT SVCZDPEF JGQPTTJCMF

Slide 17

Slide 17 text

/HJOY 6OJDPSO QSPYZ CVGGFSJOH 3BJMT

Slide 18

Slide 18 text

/HJOY 6OJDPSO serve static files

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

#SPXTFSTJEF $BDIJOH

Slide 21

Slide 21 text

#SPXTFSTJEF $BDIJOH

Slide 22

Slide 22 text

6TJOHCSPXTFSTJEFDBDIJOH

Slide 23

Slide 23 text

/FWFSVTFCSPXTFSTJEFDBDIJOH

Slide 24

Slide 24 text

$POEJUJPOBM(&5

Slide 25

Slide 25 text

1st request 2nd request

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

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!)

Slide 28

Slide 28 text

is equal to

Slide 29

Slide 29 text

FUBH\^ 3BJMT ETag is made of

Slide 30

Slide 30 text

3VCZ7FSTJPO

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

#FODINBSLT JOUIJTQSFTFOUBUJPOBSF 3VCZ 3BJMTSD

Slide 35

Slide 35 text

1FSGPSNBODF #PUUMFOFDLT JO3BJMT

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

4MPXTUVGG *FYQFSJFODFE • ActiveRecord objects creation • Resolving routes

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

"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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

$BDIJOH

Slide 47

Slide 47 text

'SBHNFOU$BDIF

Slide 48

Slide 48 text

DBDIFEP USFOE@LFZXPSET FOE

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

$BDIF%JHFTUT BLBl3VTTJBOEPMMDBDIJOHz

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

comment.update!

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

"DUJPO$BDIF

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

expires_in Sweeper expires_in expires_in expires_in Sweeper Sweeper Sweeper Sweeper Sweeper Sweeper expires_in expires_in expires_in Sweeper

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

5FNQMBUF &OHJOFT

Slide 68

Slide 68 text

FSC IBNM TMJN )PX3BJMTSFOEFS UFNQMBUFT

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

&3# FSVCJT

Slide 71

Slide 71 text

4MJN

Slide 72

Slide 72 text

)BNM

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

6OJDPSOXJUI ($EJTBCMF

Slide 78

Slide 78 text

)5513FRVFTUT time

Slide 79

Slide 79 text

6OJDPSO%FGBVMU GC

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

# 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

Slide 82

Slide 82 text

# 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

Slide 83

Slide 83 text

1SPpMJOH

Slide 84

Slide 84 text

SVCZQSPG

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

'JHIUJOHBHBJOTU TMPXRVFSJFT

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

"SQSPYZFYBNQMF

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

$PODMVTJPO

Slide 95

Slide 95 text

5SBEFPGG JOQFSGPSNBODFUVOJOH

Slide 96

Slide 96 text

%FWFMPQFST 6TFST 4FSWFST

Slide 97

Slide 97 text

13

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

13

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

5IBOLZPVGPS MJTUFOJOH