äºå¹Žãçµã¡ãŸããã çŸåšã 500äžã®åæãŠãŒã¶ãŒããã ã 1ç§ãããæ°çŸäžã®ã€ãã³ããã·ã¹ãã ãééããŠããŸãã ã¢ãŒããã¯ãã£ã®éžæã絶察ã«åŸæããŠããŸãããããã®çµæãéæããããã«å€ãã®ç 究ãšå®éšãè¡ããªããã°ãªããŸããã§ããã Elixirã¯æ°ãããšã³ã·ã¹ãã ã§ãããErlangãšã³ã·ã¹ãã ã«ã¯çç£ã§ã®äœ¿çšã«é¢ããæ å ±ããããŸããïŒãã ããAngerã®Erlangã¯äœãã§ãïŒã ElixirãDiscordã§åäœããããã«é©åãããããšè©Šã¿ãå šäœã®æ ã®çµæãããã€ãã®æèšãåŠã³ãããã€ãã®ã©ã€ãã©ãªãäœæããŸããã
ã¡ãã»ãŒãžã®ãã¡ã³å±é
Discordã«ã¯å€ãã®æ©èœããããŸãããåºæ¬çã«ã¯pub / subã«ãªââããŸãã ãŠãŒã¶ãŒã¯WebSocketã«æ¥ç¶ããŠã»ãã·ã§ã³ïŒGenServerïŒã解ããã®ã«ãããã»ã¹ïŒGenServerãïŒãæ©èœãããªã¢ãŒãErlangããŒããšã®æ¥ç¶ã確ç«ããŸãã ã®ã«ãã§äœããå ¬éãããŠããå ŽåïŒå éšã®åœåèŠåã¯ãDiscord Serverãã§ãïŒãæ¥ç¶ãããŠãããã¹ãŠã®ã»ãã·ã§ã³ã§ãã¡ã³ã¢ãŠãããŸãã
ãŠãŒã¶ãŒããªã³ã©ã€ã³ã«ãªããšããŠãŒã¶ãŒã¯ã®ã«ãã«æ¥ç¶ããæ¥ç¶ãããŠããä»ã®ãã¹ãŠã®ã»ãã·ã§ã³ã§ãã¬ãŒã³ã¹ã®ã¹ããŒã¿ã¹ãå ¬éããŸãã ä»ã«ãå€ãã®ããžãã¯ããããŸãããç°¡åãªäŸã次ã«ç€ºããŸãã
def handle_call({:publish, message}, _from, %{sessions: sessions}=state) do Enum.each(sessions, &send(&1.pid, message)) {:reply, :ok, state} end
ããã¯ã25人以äžã®ãŠãŒã¶ãŒã®ã°ã«ãŒãã«å¯ŸããŠDiscordãæåã«äœæãããšãã®éåžžã®ã¢ãããŒãã§ããã ãããã 倧å¢ã®äººã ãDiscordã䜿ãå§ãããšããç§ãã¡ã¯å¹žéã«ãæé·ã®ãè¯ãåé¡ãã«ééããŸããã ãã®çµæã / r / Overwatchã®ãããªå€ãã®DiscordãµãŒããŒã«ã¯ãäžåºŠã«æ倧30,000人ã®ãŠãŒã¶ãŒããããšããçµè«ã«éããŸããã ããŒã¯æã«ããããã®ããã»ã¹ã¯ã¡ãã»ãŒãžãã¥ãŒã«å¯Ÿå¿ã§ããªãããšãããããŸããã ããæç¹ã§ãè² è·ã«å¯ŸåŠããããã«ãã¡ãã»ãŒãžçææ©èœãæåã§ä»å ¥ããŠç¡å¹ã«ããå¿ èŠããããŸããã ãã®åé¡ãåºãŸãåã«å¯ŸåŠããå¿ èŠããããŸããã
ã®ã«ãããã»ã¹å ã§æãå¿ãããã¹ã®ãã³ãããŒã¯ããå§ããããã«ãã©ãã«ã®æãããªåå ãæããã«ããŸããã Erlangããã»ã¹éã§ã®ã¡ãã»ãŒãžã®äº€æã¯ãç§ãã¡ã«æããã»ã©å¹ççã§ã¯ãããŸããã§ããããŸããErlangã®ããã»ã¹ã·ã§ãã£ã³ã°ã®äœæ¥åäœãéåžžã«é«äŸ¡ã§ããã Erlangã³ãŒã«ããã»ã¹ã®ã¹ã±ãžã¥ãŒã«è§£é€ã«ããã1åã®
send/2
ã³ãŒã«ã®æéã¯30ÎŒsãã70ÎŒsã®éã§å€åããããšãããã£ãã ããã¯ãããŒã¯æã«ã倧ããªã®ã«ããã1ã€ã®ã€ãã³ããå ¬éããã®ã«900ããªç§ãã2.1ç§ãããããšãæå³ããŠããŸããïŒ Erlangããã»ã¹ã¯å®å šã«ã·ã³ã°ã«ã¹ã¬ããã§ãããã·ã£ãŒããå¯äžã®äžŠååãªãã·ã§ã³ã§ãããšæãããŸããã ãã®ãããªã€ãã³ãã«ã¯ããªãã®åªåãå¿ èŠã§ãããããè¯ãéžæè¢ãããããšãç¥ã£ãŠããŸããã
ã¡ãã»ãŒãžãéä¿¡ããäœæ¥ãäœããã®åœ¢ã§åæ£ãããå¿ èŠããããŸããã Erlangã®çæããã»ã¹ã¯å®äŸ¡ã§ãããããæåã«èããã®ã¯ãå ¬éããåæçš¿ãåŠçããæ°ããããã»ã¹ãåçŽã«çæããããšã§ããã ãã ãããã¹ãŠã®ãããªã±ãŒã·ã§ã³ã¯ç°ãªãã¿ã€ãã³ã°ã§çºçããå¯èœæ§ããããDiscordã¯ã©ã€ã¢ã³ãã¯ã€ãã³ãã®ç·åœ¢åå¯èœæ§ã«äŸåããŸãã ããã«ããã®ãããªãœãªã¥ãŒã·ã§ã³ã¯ãã®ã«ããµãŒãã¹ããŸããŸãå€ãã®äœæ¥ã«ãªã£ãŠãããããããŸãã¹ã±ãŒãªã³ã°ã§ããŸããã
ããŒãéã®ã¡ãã»ãŒãžåãæž¡ãã®ããã©ãŒãã³ã¹ã®æ¹åã«é¢ããããã°æçš¿ã«è§ŠçºãããŠã ManifoldãäœæããŸããã ããããŒã«ãã¯ãPIDïŒErlangã®ããã»ã¹èå¥åïŒã䜿çšããŠãªã¢ãŒãããŒãéã§ã¡ãã»ãŒãžãéä¿¡ããäœæ¥ãåæ£ããŸãã ããã«ãããé åžããã»ã¹ã¯ããªã¢ãŒãããŒããé¢ä¿ããåæ°ã ã
send/2
ãåŒã³åºã
send/2
ã Manifoldã¯ããŸããªã¢ãŒãããŒãã§PIDãã°ã«ãŒãåãã次ã«ãããã®åããŒãã®
Manifold.Partitioner
ãã»ãã¬ãŒã¿ãã«éä¿¡ããŸãã 次ã«ãåºåãæåã¯
:erlang.phash2/2
ã䜿çšããŠPIDãé 次ããã·ã¥ããã³ã¢ã®æ°ã§ã°ã«ãŒãåããåã¯ãŒã«ãŒã«éä¿¡ããŸãã æçµçã«ãã¯ãŒã«ãŒã¯å®éã®ããã»ã¹ã«ã¡ãã»ãŒãžãéä¿¡ããŸãã ããã«ãããåºåãæåãéè² è·ã«ãªããã
send/2
ãã
send/2
ç·åœ¢åå¯èœæ§ãåŒãç¶ãæäŸãããŸãã ãã®ãœãªã¥ãŒã·ã§ã³ã¯
send/2
å¹æçãªä»£æ¿ãšãªããŸããã
Manifold.send([self(), self()], :hello)
Manifoldã®é¡èãªå¯äœçšã¯ããã¡ã³ã¡ãã»ãŒãžã®CPUè² è·ãåæ£ããã ãã§ãªããããŒãéã®ãããã¯ãŒã¯ãã©ãã£ãã¯ãåæžããããšãã§ããããšã§ãã
ããŒãã®ã«ããããã®ãããã¯ãŒã¯ãã©ãã£ãã¯ã®åæž
ããããŒã«ãã¯GitHubã«ãããŸãã®ã§ãè©ŠããŠã¿ãŠãã ããã
äžè¬çãªã¯ã€ãã¯ã¢ã¯ã»ã¹ããŒã¿
Discordã¯ã äžè²«ããããã·ã¥ã䜿çšããåæ£ã·ã¹ãã ã§ãã ãã®æ¹æ³ã䜿çšããã«ã¯ãç¹å®ã®ãªããžã§ã¯ãã®ããŒããæ€çŽ¢ããããã«äœ¿çšã§ãããªã³ã°ããŒã¿æ§é ãäœæããå¿ èŠããããŸããã ã·ã¹ãã ããã°ããåäœããããã£ãã®ã§ãErlang CããŒãïŒCã³ãŒããšã®ã€ã³ã¿ãŒãã§ã€ã¹ãæ åœããããã»ã¹ïŒãä»ããŠæ¥ç¶ããããšã«ãã ããã°ãããChris Musã©ã€ãã©ãªãéžæããŸããã ããŸããããŸããããDiscordã®èŠæš¡ãæ¡å€§ããã«ã€ããŠããŠãŒã¶ãŒã®åæ¥ç¶ã«äŒŽãççºã®éã«åé¡ã«æ°ä»ãå§ããŸããã ãªã³ã°ã®ç®¡çãæ åœããErlangããã»ã¹ã¯ããªã³ã°ãžã®èŠæ±ã«å¯Ÿå¿ã§ãããã·ã¹ãã å šäœãè² è·ã«å¯Ÿå¿ã§ããªãã£ããããäœæ¥ãéåžžã«å€ããªãå§ããŸããã äžèŠãããšããœãªã¥ãŒã·ã§ã³ã¯æãããªããã«èŠããŸããããã¹ãŠã®èŠæ±ãåŠçããããã«ããã·ã³ã®ãã¹ãŠã®ã³ã¢ãæ倧éã«æŽ»çšããããã«ããªã³ã°ããŒã¿ã䜿çšããŠå€ãã®ããã»ã¹ãèµ·åããŸãã ããããããã¯éåžžã«éèŠãªäœæ¥ã§ãã ããè¯ããªãã·ã§ã³ã¯ãããŸããïŒ
ã³ã³ããŒãã³ããèŠãŠã¿ãŸãããã
- ãŠãŒã¶ãŒã¯ä»»æã®æ°ã®ã®ã«ãã«åå ã§ããŸãããå¹³åã¯5ã§ãã
- Erlang VMã»ãã·ã§ã³ãããŒãžã£ãŒã¯ãæ倧500,000ã»ãã·ã§ã³ããµããŒãã§ããŸãã
- ã»ãã·ã§ã³ã«æ¥ç¶ãããšãã圌女ã¯èå³ã®ããåã®ã«ãã®ãªã¢ãŒãããŒããèŠã€ããå¿ èŠããããŸãã
- èŠæ±/å¿çã䜿çšããå¥ã®ã¢ãŒã©ã³ããã»ã¹ãšã®éä¿¡æéã¯çŽ12ÎŒsã§ãã
ã»ãã·ã§ã³ãµãŒããŒãã¯ã©ãã·ã¥ããŠåèµ·åããå Žåããªã³ã°ãæ€çŽ¢ããã®ã«çŽ30ç§ããããŸããã ããã¯ãä»ã®ãªã³ã°ããã»ã¹ã®äœæ¥ã«é¢äžãã1ã€ã®ããã»ã¹ã®ErlangåŽã§ã®ã¹ã±ãžã¥ãŒã«è§£é€ãèæ ®ããŠããŸããã ãããã®ã³ã¹ããå®å šã«æé€ã§ããŸããïŒ
Elixirã䜿çšããå ŽåãããŒã¿ãžã®ã¢ã¯ã»ã¹ãé«éåããå¿ èŠãããå Žåãæåã«è¡ãããšã¯ETSã䜿çšããããšã§ãã ããã¯é«éã§å€æŽå¯èœãªCèŸæžã§ãã ã³ã€ã³ã®è£åŽã¯ãããŒã¿ãããã«ã³ããŒãããããããèªã¿åããããšããããšã§ãã ããŒãCã䜿çšããŠãªã³ã°ãå¶åŸ¡ããããããªã³ã°ãETSã«è»¢éããããšã¯ã§ããŸããã§ããããã®ãããçŽç²ãªElixirã§ã³ãŒããæžãæããŸãã ã ãããå®äºãããšãä»ã®ããã»ã¹ãETSããçŽæ¥ããŒã¿ãèªã¿åãããšãã§ããããã«ããªã³ã°ãææããETSã«ç¶ç¶çã«ã³ããŒããããã»ã¹ãã§ããŸããã ããã«ããããã©ãŒãã³ã¹ã¯èããåäžããŸããããETSã®èªã¿åãæäœã«ã¯çŽ7ÎŒsãããããªã³ã°å ã®å€ã®æ€çŽ¢æäœã«17.5ç§ããããŸããã ãªã³ã°ã®ããŒã¿æ§é ã¯å®éã«ã¯éåžžã«å€§ããããããETSã«ã³ããŒããŠããããèªã¿åãããšã¯ã»ãšãã©ã®æéãè²»ãããŸããã ãã£ããããŸããã ä»ã®ããã°ã©ãã³ã°èšèªã§ã¯ãå®å šãªèªã¿åãã®ããã®äžè¬çãªæå³ãåçŽã«äœæã§ããŸãã Erlangã§ãããè¡ãæ¹æ³ãå¿ èŠã§ãã
ããã€ãã®èª¿æ»ã®åŸãä»®æ³ãã·ã³é¢æ°ã䜿çšããmochiglobalã¢ãžã¥ãŒã«ãèŠã€ããŸããïŒErlangãåžžã«åãããŒã¿ãè¿ãé¢æ°ã«ééããå Žåããã®ããŒã¿ããããã»ã¹ãã¢ã¯ã»ã¹ã§ããå ±æã¢ã¯ã»ã¹ãæã€èªã¿åãå°çšããŒãã«é 眮ããŸãã ã³ããŒã¯äžèŠã§ãã mochiglobalã¯ã1ã€ã®é¢æ°ã§Erlangã¢ãžã¥ãŒã«ãäœæããŠã³ã³ãã€ã«ããããšã§ããã䜿çšããŸãã ããŒã¿ã¯ã©ãã«ãã³ããŒãããªããããæ€çŽ¢ã³ã¹ãã¯0.3ÎŒsã«æžå°ããåèšæéã¯750ããªç§ã«ççž®ãããŸããã ãã ããå®å šãªæ¯åã¯ãããŸããã å®è¡æã«ãã®ãµã€ãºã®ããŒã¿ââæ§é ãæã€ã¢ãžã¥ãŒã«ãäœæãããšãæ倧ã§1ç§ããããŸãã 幞ããªããšã«ããªã³ã°ãå€æŽããããšã¯ãã£ãã«ãªããããåãã§ãã®ä»£äŸ¡ãæ¯æããŸãã
mochiglobalãElixirã«ç§»æ€ããã¢ããã€ãŒãŒã·ã§ã³ãåé¿ããæ©èœãè¿œå ããããšã«ããŸããã ãã®ããŒãžã§ã³ã¯FastGlobalãšåŒã°ããŸã ã
åæå®è¡æ§ã®å¶é
ããŒãæ€çŽ¢ã®ããã©ãŒãã³ã¹ã«é¢ããéèŠãªåé¡ã解決ããåŸãã®ã«ãããŒãã§
guild_pid
æ€çŽ¢ãåŠçããããã»ã¹ãããã¯ã¢ãããå§ããããšã«æ°ä»ããŸããã ããŒãã®ä¿è·ã«äœ¿çšãããããŒãã®äœéæ€çŽ¢ã æ°ããåé¡ã¯ãçŽ5,000,000åã®ã»ãã·ã§ã³ããã»ã¹ããããã®ããã»ã¹ã®ãã¡10åïŒåã®ã«ãããŒãã«1åïŒãããã·ã¥ããããšããããšã§ãã ããã§ã¯ãåŠçãé«éåããŠãåé¡ã¯è§£æ±ºããŸããã§ããã æ ¹æ¬çãªçç±ã¯ãã®ã«ãã®ãã®ã¬ãžã¹ããªã«ã¢ã¯ã»ã¹ããã»ãã·ã§ã³ããã»ã¹ãã¿ã€ã ã¢ãŠãã«ãªããã¬ãžã¹ããªã®ãã¥ãŒã«ãªã¯ãšã¹ããæ®ã£ãããã§ãã ãã°ãããããšããªã¯ãšã¹ããç¹°ãè¿ãããŸãããããªã¯ãšã¹ãã絶ããèç©ãããå埩äžèœãªç¶æ ã«ãªããŸããã ä»ã®ãµãŒãã¹ããã¡ãã»ãŒãžãåä¿¡ãããšãã»ãã·ã§ã³ã¯ãããã®èŠæ±ãã¿ã€ã ã¢ãŠããããŸã§ãããã¯ããŸããããã«ãããã¡ãã»ãŒãžãã¥ãŒãè¥å€§åãããã®çµæãErlang VMå šäœã®OOMãçºçããçµæãšããŠé£éçãªåæ¢ãçºçããŸãã ã
ã»ãã·ã§ã³ããã»ã¹ãããã¹ããŒãã«ããå¿ èŠããããŸããã çæ³çã«ã¯ã倱æããçµæãé¿ããããªãå Žåã¯ãã®ã«ãã¬ãžã¹ããªã«ãããã®åŒã³åºããè¡ããªãã§ãã ããã è©Šè¡ããŸã£ããè¡ãããªããšãã«ãã¿ã€ã ã¢ãŠãã®æ¥å¢ãäžæçãªç¶æ ã«ã€ãªããç¶æ³ãçºçããªãããã«ã åè·¯ãã¬ãŒã«ãŒã䜿çšããããããŸããã§ããã ä»ã®èšèªã§ãããå®è£ ããæ¹æ³ãç¥ã£ãŠããŸããããElixirã§ãããè¡ãæ¹æ³ã¯ïŒ
ä»ã®ã»ãšãã©ã®èšèªã§ã¯ãã¢ãããã¯ã«ãŠã³ã¿ãŒã䜿çšããŠãçºä¿¡èŠæ±ãšãã®æ°ã倧ããããå Žåã®æ©æèŠåã远跡ããã»ããã©ãå¹æçã«å®è£ ã§ããŸãã Erlang VMã¯ããã»ã¹éã®èª¿æŽã«åºã¥ããŠæ§ç¯ãããŠããŸããããã®èª¿æŽã«è²¬ä»»ã®ããããã»ã¹ãããŸãããŒãããããããŸããã§ããã ããã€ãã®èª¿æ»ã®åŸãETSããŒã«å«ãŸããæ°å€ã«å¯ŸããŠæ¡ä»¶ä»ãå¢åã§ã¢ãããã¯æäœãå®è¡ãã
:ets.update_counter/4
ã«
:ets.update_counter/4
ãŸããã é©åãªäžŠååãå¿ èŠã ã£ããããETSã
write_concurrency
ã¢ãŒãã§å®è¡ããããšã¯å¯èœã§ããããå€ãèªã¿åãããšã¯å¯èœã§ã
:ets.update_counter/4
ã¯çµæãè¿ãããã§ãã ããã«ããã Semaphoreã©ã€ãã©ãªãäœæããããã®åºæ¬çãªåºç€ãåŸãããŸããã ããã¯éåžžã«äœ¿ãããããé«åž¯åå¹ ã§éåžžã«ããŸãæ©èœããŸãïŒ
semaphore_name = :my_sempahore semaphore_max = 10 case Semaphore.call(semaphore_name, semaphore_max, fn -> :ok end) do :ok -> IO.puts "success" {:error, :max} -> IO.puts "too many callers" end
ãã®ã©ã€ãã©ãªã¯ãElixirã®ã€ã³ãã©ã¹ãã©ã¯ãã£ãä¿è·ããã®ã«åœ¹ç«ã¡ãŸããã å é±ãšåæ§ã«ãåè¿°ã®ã«ã¹ã±ãŒãåæ¢ãšåæ§ã®ç¶æ³ãçºçããŸããããä»åã¯åæ¢ã¯ãããŸããã§ããã ãã¬ãŒã³ã¹ãµãŒãã¹ã¯å¥ã®çç±ã§å€±æããŸããããã»ãã·ã§ã³ãµãŒãã¹ã¯åäœããŸããã§ããããã¬ãŒã³ã¹ãµãŒãã¹ã¯ãåèµ·ååŸæ°åã§å埩ã§ããŸããã
ãã¬ãŒã³ã¹ãµãŒãã¹
åãæéã®ã»ãã·ã§ã³ãµãŒãã¹ã«ããCPU䜿çšç
ã»ããã©ã©ã€ãã©ãªã¯GitHubã«ãããŸã ã
ãããã«
ErlangãšElixirãéžæããŠäœæ¥ããããšã¯çŽ æŽãããçµéšã§ããããšãããããŸããã ç§ãã¡ãæ»ã£ãŠæåããããçŽãããšãäœåãªããããå Žåãç§ãã¡ã¯ééããªãåãéãéžã¶ã§ãããã ç§ãã¡ã®çµéšãšããŒã«ã«é¢ããã¹ããŒãªãŒããä»ã®éçºè ElixirãšErlangã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãããŸãããã®äœæ¥ã®éçšã§ç§ãã¡ã®ä»äºã«ã€ããŠè©±ããåé¡ã解決ããçµéšãç©ãã§ãããããšæããŸãã