ä¾ãã° GC ãæ¢ããã»Ruby ã¦ã§ãã¢ããªã±ã¼ã·ã§ã³ã®é«éå
æè¿ã¯ãã¯ãããã§ã¯ãã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã®å¤§åã Rails 2.3 ãã Rails 3 ã«ç½®ãæãã£ãã®ã§ãã*1ããªãªã¼ã¹åã®ãã³ããã¼ã¯ã®æç¹ã§ã¯ãã¾ãããã©ã¼ãã³ã¹ãåºãåè¦å «è¦ãã¦ãã¾ãããå ·ä½çã«ã¯ Rails 2.3 ã®æã¨æ¯ã¹ MRI 1.8.7 ã ã¨ã¬ã¹ãã³ã¹ã¿ã ã200%ãããé ãçµæã§ãããRails 3 ã«ãªã£ã¦å®è£ ã Merb core ãåãå ¥ãççµåã§ç¶ºéºã«ãªã£ãåé¢ãããå¤ãã®ãªãã¸ã§ã¯ãã¨ã»ã¡ã¢ãªãå©ç¨ããæ§ã«ãªã£ãå½±é¿ãã¨æãã¾ãã
ãã㧠Ruby ã¤ã³ã¿ããªã¿ã®å¤æ´*2ãè¡ãæ¤è¨¼ãããã¨ãã
- MRI 1.8.7
- (Rails 2.3ã¨æ¯ã¹) ç´200%é ã
- MRI 1.8.7 -> Ruby Enterprise Edition 1.8.7 2011.03 (tcmalloc ç¡å¹)
- ç´180%ä½é
- MRI 1.8.7 -> Ruby Enterprise Edition 1.8.7 2011.03 (tcmalloc æå¹)
- ç´140%ä½é
ã®ãããªæãã§ãç¡è¦ã§ããªãã»ã©é度ãé ããããã§ã¯ãªãªã¼ã¹ãå±ã¶ã¾ãã¾ããããªããã©ãã§é度ãé ãã®ãã¨ããã¨ãGC ã®å®è¡ã§ã ãã¶æéã使ã£ã¦ãã¾ãããRails3 ã§ãªãã¸ã§ã¯ããå¢ããããããã GC ã®å®è¡æéããããæ§ã«ãªã£ã¦ãã¾ã£ãããã§ãã
Unicorn ã®å°å ¥
次ã«ã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã Apache + Passenger ã®çµã¿åãããã Nginx + Unicorn ã®çµã¿åããã«å¤æ´ãã¾ãããUnicorn ã«ã¤ãã¦ç°¡åã«èª¬æããã¨ãRack ç°å¢ããã¼ããã master ããã»ã¹ã fork ãã¦åã® worker ãä½ãããã以ä¸ã®æ§ãªç¹æ§ãæã¡ã¾ãã
- fork ã«ãã worker çæã®ãããå worker ã®èµ·åãé«é
- ãã®ããåèµ·åãé«éã«ãªããåèµ·åæã®ãµã¼ãè² è·ãå°ãªã
- ãã ã¦ã¼ã¶ããã®å¦çãæããªã master ããã»ã¹ãå¿ ãåå¨ãããããã¡ã¢ãªä½¿ç¨éã1ããã»ã¹åå¢ãã
- epoll / libev çã®ã¤ãã³ãã§ãã¾ãè¤æ°æ¥ç¶ãæãã¢ãã«ã§ãªããworker 1ããã»ã¹1æ¥ç¶ã®ããå®å®æ§ãåä¸ãã
- ãã®ããã大éã®ã³ãã¯ã·ã§ã³ãè¦æ±ããå¿ è¦ãªã¦ã§ããµã¼ãã¹ã«ã¯åããªã
Unicorn ã®ç¹å¾´ã«ã¤ãã¦ããã詳ããã¯ä»¥ä¸ã®ã¨ã³ããªã¼ã§è¿°ã¹ããã¦ã¾ãã
å®éã« Apache + Passenger ã®çµã¿åãããã Nginx + Unicorn ã®çµã¿åããã«ããã¨ããããã«ã¹ã«ã¼ããããä¸ãããªããã¨ãã£ãæãã§å¤§ããªããã©ã¼ãã³ã¹æ¹åã¯è¦ããã¾ããã§ããããã㯠Unicorn ã®ç¹æ§ãé«éåãããå®å®æ§ãåèµ·åæã®ã¡ãªãã*3ãã·ã°ãã«ãéãã ãã§æä½ã§ããã·ã³ãã«ãã«éã¿ãç½®ããã¦ãããã§ãRack ã¨ããã¤ã³ã¿ã¼ãã§ã¤ã¹ãéãã¦æä½ããã Ruby ã¢ããªã±ã¼ã·ã§ã³ã®ç´æ¥çãªé度ã«ã¯ãã¾ãé¢ãã£ã¦ããªããã¨ãèãã¦ãç´å¾ã®çµæã§ããã
æ示ç㪠GC.start
ããã Unicorn ã«ã¤ãã¦èª¿ã¹ã¦ããéä¸ãTuning Unicorn 㧠Unicorn::OobGC ã¨ããé¢ç½ãã¢ããã¼ããè¦ã¤ãã¾ããã
ããã¯æå®ã®ãªã¯ã¨ã¹ãåæ°ã¢ããªã±ã¼ã·ã§ã³ãå¦çãçµããããã¦ã¼ã¶ã«ã³ã³ãã³ããè¿ããå¾ã«æ示çã« GC.start ããã¨ããã¢ããã¼ãã§ããä½ãè¯ãã®ãã¨ããã¨ãGC ãã¦ã¼ã¶ã®ãªã¯ã¨ã¹ãå¤ã§å®è¡ããããããªã¯ã¨ã¹ãä¸ã®å¦çã§ã¯ GC ãèµ°ãã«ãããªããçµæã¦ã¼ã¶ã¸ã®ã¬ã¹ãã³ã¹è¿å´é度ãé«éåãããã¨ããããã§ãã
ãããé©ç¨ããã¨ããã140%ãããé
ãã£ãé度ã 130%ã»ã©ã¸ã¨ãããã«é«éåããã¾ããããã¶ãå°è¦æ¨¡ãªã¢ããªã±ã¼ã·ã§ã³ã ã¨å¹æãçµæ§è¦è¾¼ããããªã®ã§ãããã¡ã¢ãªãã ãã¶é£ã£ã¦ã大è¦æ¨¡ãªã¢ããªã±ã¼ã·ã§ã³ã ã¨ããã使ã£ã¦ã GC ãé »ç¹ã«å®è¡ãããçµæãã¾ãéããªããªãããã§ããã
GC ãæ¢ãã
ããã§ãã£ã GC.disable ã§ã¦ã¼ã¶ããã®ãªã¯ã¨ã¹ãå¦çä¸ã¯ GC ãæ¢ãã¦ãã¾ãããªã¯ã¨ã¹ãå¤ã§ GC ããããã©ããªãããã¨æãã¤ããã®ã§è©¦ãã¦ã¿ã¾ããã
Unicorn 㯠worker ã master ãã fork ãããç¹å¾´ããããfork ããç´å¾ã®ããã»ã¹ã«å¯¾ãã¦è¨å®ã§å¦çãæ¸ããã®ã§ãunicorn.conf.rb ã®è¨å®ã«
after_fork do |server, worker| GC.disable if RAILS_ENV == 'production'
ã®ãGC.disable 㧠GC ãèµ°ããªãæ§ã«ããå¦çãå ¥ããOobGC ã®ã³ã¼ãã GC.disable æã«ã GC.start ãå®è¡ã§ããæ§ã«å¤æ´ãããã®å¾å度 GC.disable ã§æ¢ããå¦çãå ¥ãã¾ããã
- https://github.com/defunkt/unicorn/commit/c7ba76a21c5d00fb5c173cd6aa847442bbc652cb
- unicorn ã® master ãã©ã³ãã«å ¥ã£ã¦ãã®ã§ã次ã®ãªãªã¼ã¹(ãã¼ã¸ã§ã³ 4.1.2 ?) ã«ã¯åãè¾¼ã¾ããã¨æãã¾ã
ãã® GC.disable ã®ãã³ããã¼ã¯ãçµæã¯ä»¥ä¸ã§ãã
赤ã®ã°ã©ãã GC.disable ããªãã£ããµã¼ãã§ãéã®ã°ã©ãã GC.disable ãããµã¼ãã§ããããããã¾ã« GC ãã¦ã¼ã¶ããã®ãªã¯ã¨ã¹ãå¦çä¸ã¯ç¡å¹åããæ¹ãæç¶é«éãªçµæã«çµããã¾ãããRails 2.3 ã®ãµã¼ãã¨æ¯ã¹ã¦ã65%é
ãããã¨ã150%ã»ã©é«éãªçµæã¨ãªãã¾ããï¼ï¼
GC ãæ¢ãã Production ã®ã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã«é©ç¨
ã¨ããããã§ããã®ã¦ã¼ã¶ã®ãªã¯ã¨ã¹ãå¦çä¸ã¯ GC ãç¡å¹åããæ¹æ³ã§ã ãã¶é«éåãããã¨ã解ã£ãã®ã§ãä¸è¶³å ã« Unicorn åãã¦ãã Rails 2.3 ãµã¼ã(Ruby ã®ãã¼ã¸ã§ã³ã¯ MRI 1.8.7 㧠Ruby Enterprise ã§ã¯ãªã)ã«é©ç¨ããã¨ãããããã ã㧠130% ã»ã©é«éå & CPU æ¶è²»éãæ¸ã *4 ã¨ããç´ æ´ãããçµæã«ãªãã¾ããã
ãªã Rails3 ã»ã©é¡èã«é«éåããªãã£ãã®ã¯ãRails3 ã«ããã¹ã¡ã¢ãªä½¿ç¨éãå°ãªããããã¨æãã¾ãããã®å¾ Rails3 ã«å·æ°å¾ã¯å½åã® Unicorn åãã以åã® Rails 2.3 ã¢ããªã«æ¯ã¹ãæçµçã« 150% ã»ã©é«éåãã¾ããã
ã¾ã¨ã
Web ã¢ããªã±ã¼ã·ã§ã³ã®é度ã®é«éåã¯ãIO å¦çã®é«éåãé¤ãã¦ãã¾ãã¨ããã¥ã¼ãã³ã°ããã°ããã»ã©å¤§ããæ¹åããæ¹æ³ã¯ãªããªã£ã¦ããã¨æã£ã¦ã¾ããããã¦ã¼ã¶ã®ã¬ã¹ãã³ã¹å¦çä¸ã¯ GC ãæ¢ãããã®å¤ã§å®è¡ããã ãã§å¤§ããããã©ã¼ãã³ã¹ãæ¹åãã¾ãããRuby 1.8 系統ã使ã£ã¦ããµã¼ãã¹ã¯è©¦ãã¦ã¿ã価å¤ãããã¨æãã¾ãã
ãªãä»å¾ãªãªã¼ã¹ãããäºå®ã® Ruby 1.9.3 ã§ã¯ nari3 ãå®è£
ããã Lazy Sweep GC ãè¼ãã®ã§ãOobGC çãªäºã Ruby èªä½ãè¡ã£ã¦ãããGC ã®æ大å®è¡æéãæ¸ãã¨æãã®ã§ãRuby 1.9 ãªãµã¼ãã¹ã¯ 1.9.3 ã«å¤ããã ãã§ããã©ã¼ãã³ã¹æ¹åãããããã§ããã
ãã¾ãã»éç¨ãã¦ãã¦ãªã©
ã¡ã¢ãªãªã¼ã¯ã®å¯¾å¿
GC.disable ãã¦ããæéãé·ãã¨ãGC.start ããã¨ãã«å
ã®ã³ã¼ããã¡ã¢ãªãªã¼ã¯ãã¦ãã¨ããããã®ã¡ã¢ãªã¼ã解æ¾ã§ããªãæ§ãªæãã§ãã©ãã©ã Rails ã¢ããªã±ã¼ã·ã§ã³ã®ããã»ã¹ãµã¤ãºãè¥å¤§åãã¦è¡ã£ã¦ãã¾ãã¾ããã
Unicorn 㯠worker ããã»ã¹ã« SIGQUIT ãéãã¨ãã¦ã¼ã¶ã®ãªã¯ã¨ã¹ãå¦çãçµãã£ãç´å¾ã«ããã»ã¹ãæ»ãã§ãmaster ããã»ã¹ããããæ¤ç¥ãã¦ããã« fork ããä»çµã¿ãããã®ã§ã以ä¸ã®ã¦ã¼ãã£ãªãã£ãæ¸ã㦠Rack ã¬ã¤ã¤ã¼ã§å¯¾å¿ãã¾ããã
use UnicornKiller::Oom, 400 * 1024 # 使ç¨ã¡ã¢ãªã400Mãè¶ ããã¨èªåèªèº«ã« SIGQUIT use UnicornKiller::MaxRequests, 1000 # 1000 åãªã¯ã¨ã¹ããè¶ ããã¨èªåèªèº«ã« SIGQUIT
ããã»ã¹ãçµäºãã¦ãå³åº§ã« fork ã§æ°ãã worker ãä½ãããããããããªæãã®ãã£ããã¨ãã対å¿ã§ãåé¡ç¡ãéç¨ã§ãã¦ã¾ãã
Unicorn + bundler ã§ã®ãããã¤æã®åé¡
çªç¶ã¯ã¾ãã®ã§ã¡ã ããâ¦ãç¹ã« Unicorn 㯠master ããã»ã¹ã¸ã® SIGUSR2 (graceful ãªåèµ·å)ã§åèµ·åã«å¤±æããå ´åãä½äºããªãã£ãã®ããã«æã®ããã»ã¹ã¯æ£å¸¸ã«çãç¶ãããããã±ã£ã¨è¦åé¡ã«æ°ã¥ãã¾ããâ¦ã
ã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã®ãã³ããã¼ã¯ã¨ãã©ã¡ã¼ã¿ã®èª¿æ´
ãã³ããã¼ã¯ã«ã¯æå ab (apache bench) ã§ããã¤ãã® URL ã§ãã³ãã次㫠JMeter ã§æ¬çªãªã¯ã¨ã¹ãã®ä¸ä½80%ã®ãªã¯ã¨ã¹ããã¨ãã¥ã¬ã¼ããã¦ãã³ããã¨ãã¾ãããç°å¢ããä½ãã°ãã¨ã¯å©ãã ããªã®ã§ãab / JMeter ã使ãã¤ã¤ãã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã®ã¡ã¢ãªã¼æ°ãCPU ã®å©ç¨ç¶æ³ãè¦ã¦ Unicorn ã®ããã»ã¹æ°ã®èª¿æ´ã¨ Ruby Enterprise Edition ã® GC å¨ãã®ç°å¢å¤æ°ã調æ´ãã¾ããã
ãã®è¾ºã¯ãµã¼ãã¹ãã¨ã«æé©å¤ãéãã¨æãã®ã§ãã¡ã¾ã¡ã¾æ°åå¤ãã¦ããã®ãè¯ãã¨æãã¾ãã
*1:Rails 2.3 -> 3 移è¡ã¯ã¯ãã¯ãããè¦æ¨¡ã«ãªãã¨ããªã大å¤ã§ãããããããããªé¢ç½ãã¢ããã¼ãã試ããã®ã§ãããã¯ããã§ä½å¦ãã§ã話ããããã§ãã
*2: Ruby 1.9.2 åãèãã¾ãããããã¹ãéãã¾ã§ã¾ãã ãã¶æéããããï¼ãã£ãºãã«ããã¨åé¡åãåããé£ããã®ã§ä¸ç·ã«ã¢ããã°ã¬ã¼ããããã¨ã¯è¦éãã¾ãã
*3: graceful ãªåèµ·åãã»ã¨ãã©ã¨ã©ã¼ãè² è·ç¡ãè¡ããéè¦æ§ã¯ãã¦ã§ããµã¼ãã¹ãéç¨ãã¦ãæ¹ãªã解ãã¨æãã¾ã
*4: CPU 使ç¨çã¯ãã¾ãå¤ãããªãã¨æã£ã¦ããã§ãã大ããæ¸ã£ãã®ãä¸æè°ãªæãã§ãâ¦