ãåç¥ã®ããã«ãAvitoã¯ããªã倧ããªåºåãµãŒãã¹ã§ãã 倧éã®ããŒã¿ãšè² è·ããããæ¯æ3,500äžäººã®ãŠãŒã¶ãŒãšæ¯æ¥4,500äžã®ã¢ã¯ãã£ããªåºåããããŸãã ç§ã¯ãã¬ã³ã¡ã³ããŒã·ã§ã³éçºã°ã«ãŒãã®ãã¯ãã«ã«ã¢ããã€ã¶ãŒãšããŠåããŠããŸãã ç§ã®ããŒã ã¯ãã€ã¯ããµãŒãã¹ãæžããŠããŸãããä»ã§ã¯çŽ20人ãåããŠããŸãã 5k RPSã®ããã«ããã®ãã¹ãŠã«è² è·ãããã£ãŠããŸãã
éåæãã¬ãŒã ã¯ãŒã¯ã®éžæ
ãŸããç§ãã¡ãä»ããå Žæã«ã©ã®ããã«ãªã£ããã説æããŸãã 2015幎ã«ã¯ãéåæãã¬ãŒã ã¯ãŒã¯ãéžæããå¿ èŠããããŸããã
- ä»ã®ãã€ã¯ããµãŒãã¹ïŒhttpãjsonãrpcã«å¯ŸããŠå€ãã®ãªã¯ãšã¹ããè¡ãå¿ èŠãããããšã
- RedisãPostgresãMongoDBãªã©ãããŸããŸãªãœãŒã¹ããåžžã«ããŒã¿ãåéããå¿ èŠãããããšã
ãããã£ãŠãç§ãã¡ã«ã¯å€ãã®ãããã¯ãŒã¯ã¿ã¹ã¯ããããã¢ããªã±ãŒã·ã§ã³ã¯äž»ã«å ¥åºåã§å ããããŠããŸãã åœæã®Pythonã®çŸåšã®ããŒãžã§ã³ã¯3.4ã§ãasyncãšawaitã¯ãŸã 衚瀺ãããŠããŸããã§ããã Aiohttpã-ããŒãžã§ã³0.xã§ããã Facebookã®Asynchronous Tornadoã¯2010幎ã«ç»å ŽããŸããã 圌ã«å¿ èŠãªå€ãã®ããŒã¿ããŒã¹ãã©ã€ããŒãæžãããŠããŸãã ç«å·»ã¯ããã³ãããŒã¯ã§å®å®ããçµæã瀺ããŸããã 次ã«ããã®ãã¬ãŒã ã¯ãŒã¯ã§ã®éžæãåæ¢ããŸããã
3幎åŸãç§ãã¡ã¯å€ããç解ããŸããã
æåã«ãPython 3.5ã¯async / awaitã¡ã«ããºã ãåããŠããŸãã yieldãšyield fromã®éãã¯äœããTornadoãšawaitïŒãã¿ãã¬ïŒããŸãè¯ããªãïŒãšã®äžè²«æ§ãç解ããŸããã
第äºã«ãCPUãå®å šã«å æãããŠããªãå Žåã§ããã¹ã±ãžã¥ãŒã©ã§å€§éã®ã³ã«ãŒãã³ã䜿çšããããšã§ãå¥åŠãªããã©ãŒãã³ã¹ã®åé¡ãçºçããŸããã
第äžã«ãä»ã®TornadoãµãŒãã¹ã«å¯ŸããŠå€æ°ã®httpãªã¯ãšã¹ããå®è¡ããå ŽåãéåæDNSãªãŸã«ããŒãšç¹ã«åéã§ããå¿ èŠãããããšãããããŸãããæ¥ç¶ã確ç«ããæå®ãããªã¯ãšã¹ããéä¿¡ããããã®ã¿ã€ã ã¢ãŠããå°éããŸããã ãããŠäžè¬çã«ãTornadoã§httpãªã¯ãšã¹ããè¡ãæè¯ã®æ¹æ³ã¯curlã§ããããã¯ããèªäœãããªãå¥åŠã§ãã
Andrei Svetlovæ°ã¯ãPyCon Russia 2018ã§ã®ãã¬ãŒã³ããŒã·ã§ã³ã§æ¬¡ã®ããã«è¿°ã¹ãŠããŸãããäœããã®çš®é¡ã®éåæWebã¢ããªã±ãŒã·ã§ã³ãäœæãããå Žåã¯ãéåæã§äœæããŠãã ããããåŸ ã¡ãã ããã ã€ãã³ãã«ãŒãã¯ããããããããã«ã¯ãŸã£ããå¿ èŠãªãã§ãããã æ··ä¹±ããªãããã«ããã¬ãŒã ã¯ãŒã¯ã®ãžã£ã³ã°ã«ã«ç»ããªãã§ãã ããã äœã¬ãã«ã®ããªããã£ãã䜿çšããªãã§ãã ããããã¹ãŠããŸããããŸã...ã éå»3幎éãæ®å¿µãªããããã«ããŒãã®å éšãé »ç¹ã«ã¯ããŒã«ããããããå€ãã®èå³æ·±ãããšãåŠã³ã30-40ã³ãŒã«ã®å·šå€§ãªãã¬ãŒã¹ããã¯ãèŠãå¿ èŠããããŸããã
åé察åé
éåæpythonã§ç解ããæ倧ã®åé¡ã®1ã€ã¯ãyield fromãšyieldã®éãã§ãã
Guido Van Rossumãããã«ã€ããŠè©³ããæžããŠããŸãã 翻蚳ãããããªç¥èªã§å²ã¿ãŸãã
ç§ã¯ãPEP 3156ãyieldã®ä»£ããã«yield-fromã䜿çšããããšã䞻匵ããçç±ãäœåºŠãå°ããããŸãããyield fromã¯ãawaitãšã»ãŒåãã§ããããšãããããŸãã
ïŒ...ïŒ
å°æ¥ã®çµæãå¿ èŠãªå Žåã¯åžžã«yieldã䜿çšããŸãã
ããã¯æ¬¡ã®ããã«å®è£ ãããŸãã yieldãå«ãé¢æ°ã¯ïŒæããã«ïŒãžã§ãã¬ãŒã¿ãŒãªã®ã§ãäœããã®å埩ã³ãŒããå¿ èŠã§ãã 圌ããã©ã³ããŒãšåŒã³ãŸãããã å®éãã¹ã±ãžã¥ãŒã©ãŒã¯ïŒforã«ãŒãã䜿çšããŠïŒå€å žçãªæå³ã§ãå埩ãããŸããã 代ããã«ã2ã€ã®å°æ¥ã®ã³ã¬ã¯ã·ã§ã³ããµããŒãããŸãã
æåã®ã³ã¬ã¯ã·ã§ã³ããå®è¡å¯èœãã·ãŒã±ã³ã¹ãšåŒã³ãŸãã ããã¯æªæ¥ã§ããããã®çµæã¯å©çšå¯èœã§ãã ãã®ãªã¹ãã空ã«ãªããŸã§ãã¹ã±ãžã¥ãŒã©ãŒã¯1ã€ã®é ç®ãéžæãã1ã€ã®å埩ã¹ããããå®è¡ããŸãã ãã®ã¹ãããã¯ãå°æ¥ã®çµæïŒãœã±ããããèªã¿èŸŒãŸããã°ããã®ããŒã¿ãããããŸããïŒã§.sendïŒïŒãžã§ãã¬ãŒã¿ãŒã¡ãœãããåŒã³åºããŸãã ãžã§ãã¬ãŒã¿ãŒã§ã¯ããã®çµæã¯yieldåŒã®æ»ãå€ãšããŠè¡šç€ºãããŸãã sendïŒïŒãçµæãè¿ããå®äºãããšãã¹ã±ãžã¥ãŒã©ã¯çµæïŒStopIterationãå¥ã®äŸå€ããŸãã¯äœããã®ãªããžã§ã¯ãã§ããå¯èœæ§ããããŸãïŒã解æããŸãã
ïŒæ··ä¹±ããŠããå Žåã¯ããžã§ãã¬ãŒã¿ãŒã®åäœãç¹ã«.sendïŒïŒã¡ãœããã«ã€ããŠèªãã§ãã ããããããããPEP 342ãè¯ãåºçºç¹ã§ãïŒã
ïŒ...ïŒ
ã¹ã±ãžã¥ãŒã©ãŒã«ãã£ãŠãµããŒãããã2çªç®ã®å°æ¥ã®ã³ã¬ã¯ã·ã§ã³ã¯ããŸã I / OãåŸ æ©ããŠããæªæ¥ã§æ§æãããŸãã ãããã¯äœããã®åœ¢ã§select / poll / shellãªã©ã«æž¡ãããŸãã ãã¡ã€ã«èšè¿°åãI / Oã®æºåãã§ãããšãã«ã³ãŒã«ããã¯ãæäŸããŸãã ã³ãŒã«ããã¯ã¯ãå®éã«futureã«ãã£ãŠèŠæ±ãããI / Oæäœãå®è¡ããçµæã®futureå€ãI / Oæäœã®çµæã«èšå®ããfutureãå®è¡ãã¥ãŒã«ç§»åããŸãã
ïŒ...ïŒ
ä»ãç§ãã¡ã¯æãèå³æ·±ããã®ã«å°éããŸããã è€éãªãããã³ã«ãäœæããŠãããšããŸãã ãããã³ã«å ã§ãrecvïŒïŒã¡ãœããã䜿çšããŠãœã±ãããããã€ããèªã¿åããŸãã ãããã®ãã€ãã¯ãããã¡ã«å°éããŸãã recvïŒïŒã¡ãœããã¯éåæã©ãããŒã«ã©ãããããI / Oãèšå®ããå ã«èª¬æããããã«ãI / Oãå®äºãããšå®è¡ãããfutureãè¿ããŸãã ããã§ãã³ãŒãã®ä»ã®éšåãäžåºŠã«1è¡ãã€ãããã¡ãŒããããŒã¿ãèªã¿åããããšããŸãã readlineïŒïŒã¡ãœããã䜿çšãããšããŸãã ãããã¡ãŒã®ãµã€ãºãå¹³åè¡é·ããã倧ããå ŽåãreadlineïŒïŒã¡ãœããã¯ãããã¯ããã«ãããã¡ãŒãã次ã®è¡ãååŸããã ãã§ãã ãã ãããããã¡ã«è¡å šäœãå«ãŸããŠããªãå ŽåããããreadlineïŒïŒã¯ãœã±ããã§recvïŒïŒãåŒã³åºããŸãã
質åïŒreadlineïŒïŒã¯futureãè¿ãã¹ããã©ããïŒ åœŒãæã ãã€ãæååãè¿ããæã«ã¯å°æ¥ãåŒã³åºãåŽã«åãã§ãã¯ãšæ¡ä»¶ä»ãyieldã匷å¶ããã®ã¯ããŸãè¯ããããŸããã ãã®ãããreadlineïŒïŒã¯åžžã«futureãè¿ãå¿ èŠããããŸãã readlineïŒïŒãåŒã³åºããããšããããã¡ãŒããã§ãã¯ããå°ãªããšã1è¡å šäœãèŠã€ãã£ãå Žåãfutureãäœæãããããã¡ãŒããååŸããè¡ã®çµæãèšå®ããŠãfutureãè¿ããŸãã ãããã¡ãŒã«è¡å šäœããªãå Žåã¯ãI / Oãéå§ããŠãããäºæããI / Oãå®äºãããšæ°ãã«éå§ããŸãã
ïŒ...ïŒ
ããããçŸåšãI / Oããããã³ã°ãå¿ èŠãšããªãããreadlineïŒïŒãfutureãè¿ããããã¹ã±ãžã¥ãŒã©ãžã®åŒã³åºãã匷å¶ããå°æ¥ã®å€ãã®ãã®ãäœæããŠããŸããããã¯ãåŒã³åºãå ããyieldãå¿ èŠãªãããã¹ã±ãžã¥ãŒã©ãžã®åŒã³åºããæå³ããŸãã
ã¹ã±ãžã¥ãŒã©ãŒã¯ããã§ã«å®äºããŠããæªæ¥ã衚瀺ãããŠããããšã確èªããå Žåãã³ã«ãŒãã³ã«çŽæ¥å¶åŸ¡ã転éããããæªæ¥ãå®è¡ãã¥ãŒã«æ»ãããšãã§ããŸãã åŸè ã¯ããã¥ãŒã®æåŸã§åŸ æ©ããå¿ èŠãããã ãã§ãªããã¡ã¢ãªã®ããŒã«ãªãã£ïŒååšããå ŽåïŒããããã倱ããããããäœæ¥ãå€§å¹ ã«é ããªããŸãïŒè€æ°ã®å®è¡å¯èœãªã³ã«ãŒãã³ãããå ŽåïŒã
ïŒ...ïŒ
ãã®ãã¹ãŠã®æçµçãªå¹æã¯ãã³ã«ãŒãã³ã®äœæè ãyield futureã«ã€ããŠç¥ãå¿ èŠãããããšã§ãããããã£ãŠãPythonã®é¢æ°åŒã³åºãã¯ããªãé ããããè€éãªã³ãŒããããèªã¿ãããã³ã«ãŒãã³ã«åç·šæããããã®ãã倧ããªå¿ççéå£ãååšããŸãã ãŸããGlyphãšã®äŒè©±ãããå žåçãªéåæI / Oæ§é ã§ã¯é床ãéèŠã§ããããšãèŠããŠããŸãã
ãããyield-fromãšæ¯èŒããŸãããã
ïŒ...ïŒ
ãSããã®åéãã¯ãSã®iã®å ŽåïŒåéiããšã»ãŒåçã§ãããšèããããšããããããããŸããã æãåçŽãªå Žåãããã¯äºå®ã§ãããã³ã«ãŒãã³ãç解ããã«ã¯ååã§ã¯ãããŸããã 以äžãèæ ®ããŠãã ããïŒéåæI / Oã«ã€ããŠã¯ãŸã èããªãã§ãã ããïŒïŒ
def driver(g): print(next(g)) g.send(42) def gen1(): val = yield 'okay' print(val) driver(gen1())
ãã®ã³ãŒãã¯ããokayããšã42ããå«ã2è¡ãåºåããŸãïŒãã®åŸãæªåŠçã®StopIterationãçæããŸããããã¯ãgen1ã®æåŸã«yieldãè¿œå ããããšã§æå¶ã§ããŸãïŒã ãã®ã³ãŒãã¯ãpythontutor.comã®ãªã³ã¯ã§å®éã«åäœããŠããŸãã
次ã«ã次ã®ããšãèæ ®ããŸãã
def gen2(): yield from gen1() driver(gen2())
ãŸã£ããåãããã«æ©èœããŸãã ä»èããŠã ã©ã®ããã«æ©èœããŸããïŒ ãã®å Žåãã³ãŒãã¯Noneãè¿ããããforã«ãŒãã®åçŽãªyield-fromæ¡åŒµã¯ããã§ã¯äœ¿çšã§ããŸããã ïŒè©ŠããŠã¿ãŠãã ããïŒ ã Yield-fromã¯ããã©ã€ããŒãšgen1ã®éã®ãééãã£ãã«ããšããŠæ©èœããŸãã ã€ãŸããgen1ãå€ãOKã«ãããšãyield-fromãä»ããŠãã©ã€ããŒã«gen2ãçµäºãããã©ã€ããŒã42ãgen2ã«éãè¿ããšããã®å€ã¯yield-fromãä»ããŠåã³gen1ã«è¿ãããŸãïŒyieldã®çµæã«ãªããŸãïŒ ïŒ
ãã©ã€ããŒããžã§ãã¬ãŒã¿ãŒã«ãšã©ãŒãæããå Žåãåãããšãèµ·ãããŸãããšã©ãŒã¯yield-fromãééããŠããããåŠçããå éšãžã§ãã¬ãŒã¿ãŒã«éãããŸãã äŸïŒ
def throwing_driver(g): print(next(g)) g.throw(RuntimeError('booh')) def gen1(): try: val = yield 'okay' except RuntimeError as exc: print(exc) else: print(val) yield throwing_driver(gen1())
ãã®ã³ãŒãã¯ããokayããšãbahããããã³æ¬¡ã®ã³ãŒããæäŸããŸãã
def gen2(): yield from gen1() # unchanged throwing_driver(gen2())
ïŒãã¡ããã芧ãã ããïŒ goo.gl/8tnjk ïŒ
次ã«ããã®çš®ã®ã³ãŒãã«ã€ããŠèª¬æã§ããããã«ãåçŽãªïŒASCIIïŒã°ã©ãã£ãã¯ã¹ã玹ä»ããŸãã [f1-> f2-> ...-> fNïŒã䜿çšããŠãäžçªäžã®f1ïŒæãå€ãåŒã³åºããã¬ãŒã ïŒãšäžçªäžã®fNïŒæãæ°ããåŒã³åºããã¬ãŒã ïŒã®ã¹ã¿ãã¯ãè¡šããŸãããªã¹ãã®åé ç®ã¯ãžã§ãã¬ãŒã¿ãŒã§ã->ã¯yield-fromã§ãã æåã®äŸã®ãã©ã€ããŒïŒgen1ïŒïŒïŒã«ã¯yield-fromããããŸããããgen1ãžã§ãã¬ãŒã¿ãŒãããããã次ã®ããã«ãªããŸãã
[ gen1 )
2çªç®ã®äŸã§ã¯ãgen2ã¯yield-fromã䜿çšããŠgen1ãåŒã³åºãããã次ã®ããã«ãªããŸãã
[ gen2 -> gen1 )
åéåºé[...ïŒã®æ°åŠè¡šèšã䜿çšããŠãå³ç«¯ã®ãžã§ãã¬ãŒã¿ãŒãyield-fromã䜿çšããŠå¥ã®ãžã§ãã¬ãŒã¿ãŒãåŒã³åºããšãã«ãå³ç«¯ã«å¥ã®ãã¬ãŒã ãè¿œå ã§ããããšã瀺ããŸãã 巊端ã¯ããã©ã€ããŒãèŠããã®ïŒã€ãŸããã¹ã±ãžã¥ãŒã©ãŒïŒã§ãã
ããã§ãreadlineïŒïŒã®äŸã«æ»ãæºåãã§ããŸããã readlineïŒïŒã¯ãyield-fromã䜿çšããå¥ã®ãžã§ãã¬ãŒã¿ãŒã§ããreadïŒïŒãåŒã³åºããžã§ãã¬ãŒã¿ãŒãšããŠæžãæããããšãã§ããŸãã åŸè ã¯ããœã±ããããã®å®éã®å ¥åºåãè¡ãrecvïŒïŒãåŒã³åºããŸãã å·ŠåŽã«ããã¢ããªã±ãŒã·ã§ã³ã¯ãreadlineïŒïŒãåŒã³åºããžã§ãã¬ãŒã¿ãŒã§ããããããyield-fromã䜿çšããŠæ€èšããŸãã ã¹ããŒã ã¯æ¬¡ã®ãšããã§ãã
[ app -> readline -> read -> recv )
çŸåšãrecvïŒïŒãžã§ãã¬ãŒã¿ãŒã¯I / Oãèšå®ãããããæªæ¥ã«ãã€ã³ããã* yield *ïŒyield-fromïŒã§ã¯ãããŸããïŒã䜿çšããŠã¹ã±ãžã¥ãŒã©ãŒã«æž¡ããŸãã futureã¯ãã¹ã±ãžã¥ãŒã©ã®äž¡æ¹ã®yield-fromç¢å°ã«æ²¿ã£ãŠå·ŠåŽã«ç§»åããŸãïŒã[ãã®å·ŠåŽã«ãããŸãïŒã ã¹ã±ãžã¥ãŒã©ã¯ããžã§ãã¬ãŒã¿ã®ã¹ã¿ãã¯ãå«ãŸããŠããããšãç¥ããªãããšã«æ³šæããŠãã ããã 圌ãç¥ã£ãŠããã®ã¯ã圌ãäžçªå·Šã®ãžã§ãã¬ãŒã¿ãŒãå«ãã§ããããšããããŠåœŒãã¡ããã©æªæ¥ãçºè¡ããããšã§ãã I / Oãå®äºãããšãã¹ã±ãžã¥ãŒã©ã¯å°æ¥ã®çµæãèšå®ãããžã§ãã¬ãŒã¿ãŒã«éãè¿ããŸãã çµæã¯äž¡æ¹ã®yiled-fromç¢å°ã«æ²¿ã£ãŠrecvãžã§ãã¬ãŒã¿ãŒã«å³ã«ç§»åããrecvãžã§ãã¬ãŒã¿ãŒã¯ãœã±ããããèªã¿åããããã€ããyieldçµæãšããŠåãåããŸãã
ã€ãŸããyield-fromãã¬ãŒã ã¯ãŒã¯ã¹ã±ãžã¥ãŒã©ã¯ãåè¿°ã®yieldããŒã¹ã®ãã¬ãŒã ã¯ãŒã¯ã¹ã±ãžã¥ãŒã©ãšåãããã«I / OæäœãåŠçããŸãã *ãããïŒ*ã¹ã±ãžã¥ãŒã©ãŒã¯readlineïŒïŒãšreadïŒïŒã®éããŸãã¯readïŒïŒãšrecvïŒïŒã®éããŸãã¯ãã®éã®å¶åŸ¡ã®è»¢éã«åå ããªããããfutureãæ¢ã«å®è¡ãããŠããå Žåãæé©åã«ã€ããŠå¿é ããå¿ èŠã¯ãããŸããã ãããã£ãŠãappïŒïŒãreadlineïŒïŒãåŒã³åºããreadlineïŒïŒããããã¡ãŒããã®èŠæ±ãæºããããšãã§ããå ŽåïŒreadïŒïŒãåŒã³åºããã«ïŒãã¹ã±ãžã¥ãŒã©ãŒã¯ãŸã£ããåå ããŸãã-ãã®å Žåã®appïŒïŒãšreadlineïŒïŒã®çžäºäœçšã¯ããã€ãã³ãŒãã€ã³ã¿ãŒããªã¿ãŒã«ãã£ãŠå®å šã«åŠçãããŸãPython ã¹ã±ãžã¥ãŒã©ãŒã¯ããåçŽã«ããããšãã§ããã³ã«ãŒãã³ã®åŒã³åºãããšã«äœæããã³ç Žæ£ãããå°æ¥ã®ã¹ã±ãžã¥ãŒã©ãŒããªããããã¹ã±ãžã¥ãŒã©ãŒã«ãã£ãŠäœæããã³ç®¡çãããå°æ¥ã®æ°ã¯å°ãªããªããŸãã ãŸã å¿ èŠãªæªæ¥ã¯ãããšãã°recvïŒïŒã«ãã£ãŠäœæãããå®éã®I / Oãè¡šãæªæ¥ã ãã§ãã
ãããŸã§èªãã ããšãããã°ãå ±ããåããã«å€ããŸãã å®è£ ã®è©³çŽ°ã®å€ãã¯çç¥ããŸããããäžèšã®å³ã¯æ¬è³ªçã«å³ãæ£ããåæ ããŠããŸãã
ãã1ã€ææããŠããããããšããããŸãã *ã³ãŒãã®äžéšã«yield-fromã䜿çšãããä»ã®éšåã«yieldã䜿çšãããããšãã§ããŸãã ãã ããæ©çãŸãã確ä¿ããã«ã¯ããã§ãŒã³å ã®ãã¹ãŠã®ãªã³ã¯ã«ãã³ã«ãŒãã³ã ãã§ãªãæªæ¥ãå¿ èŠã§ãã yield-fromã䜿çšããããšã«ã¯ããã€ãã®å©ç¹ãããããããŠãŒã¶ãŒã«ãã€yieldã䜿çšããããèŠããŠããå¿ èŠã¯ãªããyield-fromã®å Žåã¯åžžã«yield-fromã䜿çšããæ¹ãç°¡åã§ãã ç°¡åãªè§£æ±ºçã§ã¯ãrecvïŒïŒãyield-fromã䜿çšããŠå°æ¥ã®I / Oãã¹ã±ãžã¥ãŒã©ã«æž¡ãããšãã§ããŸãã__iter__ã¡ãœããã¯ãå®éã«æªæ¥ãæäŸãããžã§ãã¬ãŒã¿ã§ãã
ïŒ...ïŒ
ãããŠããäžã€ã yield-fromã¯ã©ã®å€ãè¿ããŸããïŒ ããã¯ã*å€éš*ãžã§ãã¬ãŒã¿ãŒã®æ»ãå€ã§ããããšãããããŸãã
ïŒ...ïŒ
ãããã£ãŠãç¢å°ã¯ãå·Šãšå³ã®ãã¬ãŒã ã* yielding *ã¿ãŒã²ããã«æ¥ç¶ããŸãããéåžžã®æ»ãå€ãéåžžã®æ¹æ³ã§äžåºŠã«1ã€ã®ã¹ã¿ãã¯ãã¬ãŒã ãæž¡ããŸãã äŸå€ã¯åãæ¹æ³ã§ç§»åãããŸãã ãã¡ããããããããã£ããããã«ã¯ãåã¬ãã«ã§try / exceptãå¿ èŠã§ãã
éåæ察åé
def coroïŒïŒ^ y = aããã®åé | async def async_coroïŒïŒïŒ y = aãåŸ ã€ |
0 load_global | 0 load_global |
2 get_yield_from_iter | 2 get_awaitable |
4 load_const | 4 load_const |
6 yield_from | 6 yield_from |
8 store_fast | 8 store_fast |
10 load_const | 10 load_const
|
12 return_value | 12 return_value |
å€ãåŠæ ¡ãšæ°ããåŠæ ¡ã®2ã€ã®ã³ã«ãŒãã³ã«ã¯ãããããªéãã1ã€ãããããŸããã
ãªãããã ããªã®ã§ããïŒ ç«å·»ã¯åçŽãªåéã䜿çšããŸãã ããŒãžã§ã³5ããåã§ã¯ããã®ã³ãŒã«ãã§ãŒã³å šäœãyieldãä»ããŠæ¥ç¶ããŸããããã¯ããã©ãã€ã ããã®æ°ããã¯ãŒã«ãªyieldãšã®äºææ§ãäžååã§ãã
æãåçŽãªéåæãã³ãããŒã¯
ç·åçãªãã¹ãã«åŸã£ãŠã®ã¿éžæãããæ¬åœã«è¯ããã¬ãŒã ã¯ãŒã¯ãèŠã€ããããšã¯å°é£ã§ãã å®ç掻ã§ã¯ãå€ãã®ããšãããŸããããªãããšããããŸãã
AiohttpããŒãžã§ã³3.4.4ãTornado 5.1.1ãuvloop 0.11ã䜿çšããIntel XeonãµãŒããŒããã»ããµãCPU E5 v4ã3.6 GHzã䜿çšããPython 3.6.5ã§WebãµãŒããŒã®ç«¶äºåããã§ãã¯ãå§ããŸããã
ãã€ã¯ããµãŒãã¹ã®å©ããåããŠè§£æ±ºããéåæã¢ãŒãã§åäœããå žåçãªã¿ã¹ã¯ã¯æ¬¡ã®ããã«ãªããŸãã ãªã¯ãšã¹ããåãåããŸãã ããããã«ã€ããŠããããã€ã¯ããµãŒãã¹ã«å¯ŸããŠ1ã€ã®ãªã¯ãšã¹ããè¡ããããããããŒã¿ãååŸããããã«éåæã§å¥ã®2ã€ãŸãã¯3ã€ã®ãã€ã¯ããµãŒãã¹ã«ç§»åããããŒã¿ããŒã¹ã®ã©ããã«ããŒã¿ãæžã蟌ãã§çµæãè¿ããŸãã ç§ãã¡ãåŸ ã€å€ãã®ãã€ã³ããå€æããŸããã
ããç°¡åãªæäœãå®è¡ããŸãã ãµãŒããŒã®é»æºãå ¥ããŠã50ããªç§ã¹ãªãŒãããŸãã ã³ã«ãŒãã³ãäœæããŠå®äºããŸãã 競äºåã®ãããµãŒããŒã§å€ãã®ã³ã«ãŒãã³ãåæã«ã¹ãã³ãããšããäºå®ã®ããã«ã蚱容å¯èœãªé 延ã䌎ãéåžžã«å€§ããªRPSïŒå®å šã«åæããããã³ãããŒã¯ã§èŠããããã®ãšåçšåºŠã§ã¯ãªããããããŸããïŒã¯ãããŸããã
@tornado.gen.coroutine def old_school_work(): yield tornado.gen.sleep(SLEEP_TIME) async def work(): await tornado.gen.sleep(SLEEP_TIME)
ããŒã-GET HTTPãªã¯ãšã¹ãã æèŠæé-300ç§ã1ç§-ãŠã©ãŒã ã¢ãããè² è·ã®5åã®ç¹°ãè¿ãã
ãµãŒãã¹å¿çæéã®ããŒã»ã³ã¿ã€ã«ã®çµæã
ããŒã»ã³ã¿ã€ã«ãšã¯äœã§ããïŒ
ããã€ãã®å€§ããªæ°åããããŸãã 95ããŒã»ã³ã¿ã€ã«Xã¯ããã®ãµã³ãã«ã®å€ã®95ïŒ
ãXæªæºã§ããããšãæå³ããŸãã5ïŒ
ã®ç¢ºçã§ã¯ãæ°å€ã¯Xãã倧ãããªããŸãã
Aiohttpã¯ãã®ãããªç°¡åãªãã¹ãã§1000 RPSã§çŽ æŽãããä»äºãããããšãããããŸãã ãããŸã§ã®ãšããã uvloopã¯ãããŸãã ã
ãã«ããŒãããæ§ïŒæ©çãŸãïŒããã³æ°ïŒéåæïŒåŠæ ¡ã®ã³ã«ãŒãã³ãšæ¯èŒããŠãã ããã èè ã¯ãéåæã®äœ¿çšã匷ããå§ãããŸãã ããããæ¬åœã«ã¯ããã«é«éã§ããããšã確èªã§ããŸãã
1200 RPSã§ã¯ããã«ããŒãã¯ãæ°ããåŠæ ¡ã®ã³ã«ãŒãã³ã䜿çšãããšããŠãããã§ã«ããããå§ããå€ãåŠæ ¡ã®ã³ã«ãŒãã³ã䜿çšãããã«ããŒãã¯å®å šã«å¹ãé£ã°ãããŸããã 50ããªç§ã¹ãªãŒããããã€ã¯ããµãŒãã¹ã80ããªç§ãæ åœããå Žåãããã¯ã©ã®ã²ãŒãã«ãå ¥ããŸããã
1,500 RPSã®æ°ããåŠæ ¡ã®ãã«ããŒãã¯å®å šã«gaveããŸããããAiohttpã¯3,000 RPSã®å¶éããã¯ã»ã©é ãã§ãã æãèå³æ·±ãã®ã¯ãŸã æ¥ãŠããŸããã
Pyflameãå®çšçãªãã€ã¯ããµãŒãã¹ã®ãããã¡ã€ãªã³ã°
ããã»ããµã§ãã®ç¬éã«äœãèµ·ãã£ãŠããã®ãèŠãŠã¿ãŸãããã
Pythonã®éåæãã€ã¯ããµãŒãã¹ãæ¬çªç°å¢ã§ã©ã®ããã«æ©èœããããèãåºãããšããç§ãã¡ã¯ãããäœã«ã¶ã€ãã£ãã®ããç解ããããšããŸããã ã»ãšãã©ã®å Žåãåé¡ã¯CPUãŸãã¯èšè¿°åã«ãããŸããã Uberã«ã¯ãptraceã·ã¹ãã ã³ãŒã«ã«åºã¥ããPyflameãããã¡ã€ã©ãŒãšããåªãããããã¡ã€ãªã³ã°ããŒã«ããããŸãã
ã³ã³ããã§ãµãŒãã¹ãéå§ããã³ã³ããã«æŠéè² è·ãããå§ããŸãã å€ãã®å Žåãããã¯ããããªäœæ¥ã§ã¯ãããŸãããæŠéäžã®è² è·ãäœæããããšã¯ãè² è·ãã¹ããå€èŠ³ãããã³ãã¹ãŠã§æ£åžžã«æ©èœããããã«åæãã¹ããå®è¡ããããšãå€ãããã§ãã ããªãã¯åœŒã«æŠéè² è·ãããããšãããã§ãã€ã¯ããµãŒãã¹ãéãå§ããŸãã
åäœäžã«ããã®ãããã¡ã€ã©ãŒã¯åŒã³åºãã¹ã¿ãã¯ã®ã¹ãããã·ã§ãããäœæããŸãã ãµãŒãã¹ãå€æŽããããšã¯ã§ããŸãããè¿ãã§pyflameãå®è¡ããã ãã§ãã äžå®æéã«äžåºŠã¹ã¿ãã¯ãã¬ãŒã¹ãåéããã¯ãŒã«ãªèŠèŠåãè¡ããŸãã ãã®ãããã¡ã€ã©ãŒã¯ãç¹ã«cProfileãšæ¯èŒããå ŽåããªãŒããŒããããã»ãšãã©ãããŸããã Pyflameã¯ãã«ãã¹ã¬ããããã°ã©ã ããµããŒãããŠããŸãã ãã®è£œåãprodã§çŽæ¥èµ·åããŸããããããã©ãŒãã³ã¹ã¯ããã»ã©äœäžããŸããã§ããã
ããã§ãX軞ã¯ãã¹ã¿ãã¯ãã¬ãŒã ããã¹ãŠã®Pythonã¹ã¿ãã¯ãã¬ãŒã ã®ãªã¹ãã«èŒã£ãŠãããšãã®æéãåŒã³åºãã®æ°ã§ãã ããã¯ãã¹ã¿ãã¯ã®ãã®ç¹å®ã®ãã¬ãŒã ã§è²»ãããããã»ããµæéã®ããããã®éã§ãã
ã芧ã®ãšãããaiohttpã§ã®ã»ãšãã©ã®æéã¯ã¢ã€ãã«ç¶æ ã«ãªããŸãã ãã°ãããïŒããã¯ãã»ãšãã©ã®æéã§ãããã¯ãŒã¯ã³ãŒã«ãåŠçããããã«ãéåæãµãŒãã¹ã«å¿ èŠãªãã®ã§ãã ãã®å Žåã®ã¹ã¿ãã¯ã®æ·±ãã¯çŽ15ãã¬ãŒã ã§ãã
åãè² è·ã®ãã«ããŒãïŒ2çªç®ã®åçïŒã§ã¯ãã¢ã€ãã«ã«è²»ããããæéãå€§å¹ ã«ççž®ããããã®å Žåã®ã¹ã¿ãã¯æ·±åºŠã¯çŽ30ãã¬ãŒã ã§ãã
ãã¡ããsvgãžã®ãªã³ã¯ã§ãã
ããè€éãªéåæãã³ãããŒã¯
async def work(): # await asyncio.sleep(SLEEP_TIME) class HardWorkHandler(tornado.web.RequestHandler): timeout_time = datetime.timedelta(seconds=SLEEP_TIME / 2) async def get(self): await work() # await tornado.gen.multi([work(), work()]) # try: await tornado.gen.with_timeout(self.timeout_time, work()) except tornado.util.TimeoutError: # pass
125ããªç§ã®ã©ã³ã¿ã€ã ãå¿ èŠã§ãã
uvloopã䜿çšãããã«ããŒãã®æ¹ãããŸããããŸãã ããããAiohttp uvloopã¯ããã«åœ¹ç«ã¡ãŸãã Aiohttpã¯2300-2400 RPSã§åäœãæªããªããuvloopã䜿çšãããšè² è·ç¯å²ãå€§å¹ ã«æ¡å€§ããŸãã ã€ã³ããŒãã®1ã€ã®è¡ããããŠä»ãããªãã¯ã¯ããã«çç£çãªãµãŒãã¹ãæã£ãŠããŸãã
ãŸãšã
ä»æ¥ç§ãããªãã«äŒãããã£ãããšãèŠçŽããŸãã
- ãŸããããªãã®éã®é·ãã³ã«ãŒãã³ãååšããç¹å®ã®äººå·¥ãã³ãããŒã¯ãéå§ããŸããã ç§ãã¡ã®ãã¹ãã§ã¯ãAiohttpã¯Tornadoããã2.5ååªããããã©ãŒãã³ã¹ã瀺ããŸããã
- 第äºã®äºå®ã Uvloopã¯ãAiohttpã®ããã©ãŒãã³ã¹ã®åäžã«éåžžã«åœ¹ç«ã¡ãŸãïŒTornadoãããåªããŠããŸãïŒã
- Pyflameã«ã€ããŠèª¬æããŸãããPyflameã䜿çšããŠãå®çšŒåç°å¢ã§ã¢ããªã±ãŒã·ã§ã³ãçŽæ¥ãããã¡ã€ã«ããããšããããããŸãã
- ãŸããïŒawaitïŒvs yieldããã®åéã«ã€ããŠã話ããŸããã
ãããã®ãã³ãããŒã¯ã®çµæãç§ãã¡ã®æšå¥šããŒã ïŒããã³ä»ã®äžéšïŒã¯ãå®çšŒåç°å¢ã§ã®Pythonã®ãã€ã¯ããµãŒãã¹ã«ã€ããŠãTornadoãšãšãã«ã»ãŒå®å šã«Aiohttpã«ç§»è¡ããŸããã
- æŠéãµãŒãã¹ã®å ŽåãCPUæ¶è²»ã¯2å以äžæžå°ããŸããã
- httpãªã¯ãšã¹ãã®ã¿ã€ã ã¢ãŠããå°éãå§ããŸããã
- é 延ãµãŒãã¹ã¯2ã5åæžå°ããŸããã
ããããã³ãããŒã¯ãžã®ãªã³ã¯ã§ãã èå³ãããã°ããããç¹°ãè¿ãããšãã§ããŸãã ãæž èŽããããšãããããŸããã 質åããŠãã ãããç§ã¯ãããã«çããããšããŸãã