
å€ãã®éçºè
ã¯ãå€ãã®å ŽåãããŒã¿ããŒã¹ããã®ã¿ããŒã¿ãåä¿¡ããããããã€ãã®ããŒãã«ã®ãã£ãã·ã¥ãä¿æãããšãããžã¬ã³ãã«çŽé¢ããŸãã åºæ¬çã«ããããã¯ã¬ã³ãŒããã»ãšãã©å«ãŸãªããã£ã¬ã¯ããªã§ãããåžžã«æå
ã«å¿
èŠã§ãã ããã¯ããªãŠããã®åé¡ã§ããããã®èšäºã§ã¯å¯ŸåŠããŸããã
.NETäžã®ãã©ã³ã¹ããŒãç£èŠã·ã¹ãã ã®è² è·ã®é«ããµãŒããŒãèšèšãããšãã«ãåãåé¡ãç®ã®åã§çºçããŸããã ãã®çµæããã£ãã·ã¥ãå¿
èŠã§ããããšã決å®ãããŸããã èŸæžãã£ãã·ã¥ã¯ãConcurrentDictionaryã®ã©ãããŒã«æ ŒçŽãããããã«ãªããŸããã ãã®ãªãã·ã§ã³ã¯ãã¹ã¬ããã»ãŒããªãã£ã¯ã·ã§ããªçšã®æšæºã®.NETããŒã«ã§ãããããããŸã調æ»ããããšãªãæ¡çšãããŸããã ä»ããããã®ãœãªã¥ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ããã¹ããããšãã§ãã ããã«ã€ããŠã¯ãå®éã«ã¯èšäºã§ãã ãŸãããã®èšäºã®æåŸã«ã¯ãConcurrentDictionaryå
ã§ã®é
çœ®æ¹æ³ã«é¢ããå°ãã®ç ç©¶ããããŸãã
åé¡ã®å£°æããŒãšå€ã®ãã¢ã®ã¹ã¬ããã»ãŒããªã³ã¬ã¯ã·ã§ã³ãå¿
èŠã§ããããã«ãããæ¬¡ã®ããšãå¯èœã«ãªããŸãã
- èå¥åããŒãæã€ãªããžã§ã¯ããèŠæ±ãã-ãã¡ãããæãé »ç¹ã«äœ¿çšãããŸãã
- æ°ããèŠçŽ ã倿Žãåé€ã远å ããããšã¯ãŸãã§ãããã¹ã¬ããã®å®å
šæ§ã確ä¿ããå¿
èŠããããŸãã
- å€ã®æäœ-ãã¹ãŠã®å€ãèŠæ±ããå€ãªããžã§ã¯ãã®ããããã£ã§æ€çŽ¢ããŸãã
æ¡é
3ã¯èŸæžã³ã¬ã¯ã·ã§ã³ã§ã¯äžè¬çã§ã¯ãªãããããã®æ§æã®äž»ãªãã¬ãŒããšãªããŸãã ãã ããã«ãã¯ã¢ããããŒãã«ã®ãã£ãã·ã¥ã䜿çšããå Žåããã®ãããªç¶æ³ã¯é¿ããããŸããïŒããšãã°ãç·šéã®ããã«ç®¡çããã«ã«ãã£ã¯ã·ã§ããªå
šäœã衚瀺ããã®ã¯ç°¡åã§ãïŒã
ãã£ãã·ã¥ã䜿çšãããããŸããŸãªã·ã¹ãã ãæ€èšããŠã¿ãŸãããã ãããã¯ãèŸæžã䜿çšããæäœã®é »åºŠãç°ãªããŸãã ãããã®æäœã®ã¿ã€ãã圢åŒåããŸãã
- GET-ããŒã«ãããªããžã§ã¯ãã®ãªã¯ãšã¹ãã
- ADD-æ°ããããŒã§æ°ãããªããžã§ã¯ãã远å ïŒãã®ãããªããŒãæ¢ã«ååšããå Žåã¯äžæžãïŒ
- UPDATE-æ¢åã®ããŒã®æ°ããå€ïŒããŒããªãå Žåã¯äœãããŸããïŒ
- SEARCH-ã€ãã¬ãŒã¿ãŒã䜿çšããŸãããã®å Žåãæåã®é©åãªå€ãæ€çŽ¢ããŸã
ãã¹ãåå è
ã®ãªã¹ã- ConcurrentDictionary ã ããã¯ãã¹ã¬ããã»ãŒããçµ±åãããMicrosoftã®ã¿ãŒã³ããŒãœãªã¥ãŒã·ã§ã³ã§ãã 䟿å©ãªã¡ãœããTryGetValueãTryAddãTryUpdateãAddOrUpdateãTryDeleteãå®è£
ããŸããããã«ãããç«¶å解決ããªã·ãŒãç°¡åã«èšå®ã§ããŸãã å®è£
æ©èœã«ã€ããŠã¯ãèšäºã®æåŸã§èª¬æããŸãã
- Monitorãä»ããããã¯ä»ãã®èŸæž ã æãæ£é¢ããã®è§£æ±ºçã¯ããã¹ãŠã®éã¹ã¬ããã»ãŒãæäœãããã¯æ§é ã«ã©ãããããããšã§ãã
- ReaderWriterLockãä»ããããã¯ä»ãã®èŸæž ã 以åã®ãœãªã¥ãŒã·ã§ã³ã®æé©å-æäœã¯èªã¿åãæäœãšæžãèŸŒã¿æäœã«åããããŸãã ãããã£ãŠãè€æ°ã®ã¹ããªãŒã ãåæã«èªã¿åãããšãã§ããèšé²ã«ã¯æä»çã¢ã¯ã»ã¹ãå¿
èŠã§ãã
- ReaderWriterLockSlimãä»ããããã¯ä»ãã®èŸæž ã åºæ¬çã«åãã§ãããæ°ããã¯ã©ã¹ã䜿çšããŸãïŒååž°å¶åŸ¡èšå®ã远å ïŒã ãã®ã¿ã¹ã¯ã®ã³ã³ããã¹ãã§ã¯ãReaderWriterLock以å€ã衚瀺ããå¿
èŠã¯ã»ãšãã©ãããŸããã
- Wintellect PowerThreadingã©ã€ãã©ãªã®OneManyResourceLockerãä»ããããã¯ä»ãèŸæž -Jeffrey Richterã«ããReaderWriterLockã®ããªãããŒãªå®è£
ã NuGetããã±ãŒãžã§ã¯ãªããå
¬åŒãµã€ãã®ããŒãžã§ã³ã䜿çšãããããšãæç¢ºã«ããŸããããŒãžã§ã³ãç°ãªããããæ°ã«å
¥ããªãã£ãããã§ãã
- Hashtable.Synchronized ã ãŸããMicrosoftã®æ¢æã®ãœãªã¥ãŒã·ã§ã³-ã¹ã¬ããã»ãŒããªã€ã³ãã¯ãµãŒãæäŸããŸãã éãžã§ããªãã¯ã³ã¬ã¯ã·ã§ã³ïŒããã¯ã¹åãèªã¿ãããã®äœäžïŒã§ãããTryãã¬ãã£ãã¯ã¹ãæã€ã¡ãœããããªãããã䜿çšããã®ã¯äžäŸ¿ã§ãïŒåæã«è¿œå /æŽæ°ããããã®ããªã·ãŒãèšå®ããããšã¯äžå¯èœã§ãïŒã
ãã³ãã©ãŒã®å®è£
æ¹æ³ãæ£ç¢ºã«ç°¡æœã«èª¬æããŸãã- GETæäœïŒãã¹ãŠã®åå è
ã¯ãIDictionaryã€ã³ã¿ãŒãã§ã€ã¹ããã¹ã¬ããã»ãŒããªTryGetValueã¡ãœããã䜿çšããŸãã Hashtableã®å Žåãã¿ã€ãã³ãŒãåãããã€ã³ãã¯ãµãŒã䜿çšãããŸãã
- ADDæäœïŒConcurrentDictionaryã®å Žå-AddOrUpdateãDictionaryã®å Žå-ããã¯ã®æžã蟌ã¿ãšã€ã³ãã¯ãµãŒã®è¿œå ãHashtableã®å Žå-ããã¯ãªãã®ã€ã³ãã¯ãµãŒã®è¿œå ã
- UPDATEæäœïŒConcurrentDictionaryã®å Žåãæåã«TryGetValueãæ¬¡ã«TryUpdateã
ãã®ã¡ãœããã¯ãããã2ã€ã®ã¡ãœããéã§äžŠè¡æŽæ°ãå®è¡ã§ãããšããç¹ã§è峿·±ãïŒãã¹ãäžã«ãæããã«ãªã£ãïŒã ãã®å ŽåãoldValueãTryUpdateã«æž¡ãããããããã®ãŸããªã±ãŒã¹ã§ã¯æžãæãã倱æããŸãã ãã£ã¯ã·ã§ããªã®å ŽåãContainsKeyãä»ããŠå¯çšæ§ã確èªããæåããå Žåã¯æžã蟌ã¿ããã¯ãèšå®ããŠå€ãäžæžãããŸãã Hashtableçšã®äŸ¿å©ãªTryUpdateããªããããããŒã®ååšã確èªããæéãããããã远å ã®å Žåã®ããã«ãå€ã¯ã€ã³ãã¯ãµãŒã«ãã£ãŠäžæžããããŸãïŒãã®ã³ã¬ã¯ã·ã§ã³ã§ã¯ãããã¯éèŠã§ã¯ãããŸãã-ãšã«ããããªãæªãã£ãã§ãïŒã - æäœSEARCH ïŒConcurrentDictionaryã®å ŽåãLINQã®FirstOrDefaultã䜿çšãããæ®ãã®å ŽåãåãFirstOrDefaultã«å¯ŸããŠèªã¿åãããã¯ã䜿çšãããŸãã
詊éšå°ãã¹ãçšã«ãã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ãäœæãããŸããïŒ
ãªã³ã¯ ïŒã
- ç¹å®ã®ãã¹ãŠã®ã¿ã€ãã®æäœãåŠçã§ããäžé£ã®ãã³ãã©ãŒãäœæãããŸãã
- Nåã®èŠçŽ ã®ãã£ã¯ã·ã§ããªãäœæãããŸãïŒããã©ã«ãã§ã¯10,000ïŒã
- Mã®éã®ããŸããŸãªã¿ã€ãã®ã¿ã¹ã¯ã®ã³ã¬ã¯ã·ã§ã³ãäœæãããŸãïŒããã©ã«ãã§ã¯10,000ïŒã
- åãã³ãã©ãŒã¯ãçæãããèŸæžå
ã®ãã¹ãŠã®ã¿ã¹ã¯ïŒãã¹ãŠã®ãã³ãã©ãŒã«å
±éïŒã®äžŠååŠçãå®è¡ããŸãã
- å®éšïŒãã€ã³ã2ã4ïŒã¯ãæå®ãããåæ°ïŒããã©ã«ãã§ã¯10åïŒå®è¡ãããååŸãããæéã¯å¹³åãããŸãã æž¬å®ã¯ãCore 2 Quad 2.66 GHzãš8 GBã®ã¡ã¢ãªãæèŒãããã·ã³ã§è¡ãããŸããã
ããã©ã«ãå€ã¯éåžžã«å°ããã§ãããå€ãå¢ãããŠãåºæ¬çã«ã¯äœãå€ãããŸããã
詊éšçµæãã¹ãã¯ãæäœã®ã¿ã€ãããšã«ç°ãªã忣ãªãã·ã§ã³ã䜿çšããŠå®è¡ãããããŒãã«ã倧ããããããšã倿ããŸãããå
šäœãããã§ç¢ºèªã§ããŸãïŒ
ãªã³ã¯ ïŒ ããããããããããã«ãåèšæäœæ°ã®å€ã«ããèªã¿åãã®å²åã«å¿ããŠãã€ã¯ãç§åäœã§ãã¹ãå®è¡æéã®ã°ã©ãã瀺ããŸãïŒæžãèŸŒã¿æäœã¯20ïŒ
ã«åºå®ãããæ®ãã¯ããŒã«ãã£ãŠèªã¿åãããŸãïŒã
çµè«ãã¹ãŠã®åå è
ã®ããã©ãŒãã³ã¹ã¯ãæžãèŸŒã¿æäœã®åæ°ã«é¢ä¿ãªããå€ããšã®èªã¿åãåæ°ã«æ¯äŸããŠäœäžããŸãã
- ConcurrentDictionary ã å®éšã«ããããã®ããŒã«ã¯ãã®ã¿ã¹ã¯ã«æé©ã§ããããšã瀺ãããŠããŸãã å€ã«ããèªã¿åãã¯ããã©ãŒãã³ã¹ã«å€§ãã圱é¿ããŸãããä»ã®åå è
ãããé«éã§ãã
- èŸæž+ã¢ãã¿ãŒ ã 倧å¹
ã«é
ããæåŸ
ãããçµæã
- èŸæž+ ReaderWriterLock ã 以åã®ããŒãžã§ã³ã®æé©åããã¹ãŠæåŸ
ãããŠããŸãã
èšé²æäœãå€ãã»ã©ãå·®ã¯å°ãããªãããšã«æ³šæããŠãã ããã ããæç¹ããããããã¯ããã»ã¹èªäœã®ãªãŒããŒããããå°ãããªããããMonitorãããã«å¥œãŸããç¶æ
ã«ãªããŸãã - èŸæž+ ReaderWriterLockSlim äœããã®çç±ã§ãç§ã¯åçŽãªã¢ãã¿ãŒã§ãããäœãšã倱ããŸããã 匷åãããæ©èœïŒä»¥åã®ããŒãžã§ã³ãšæ¯èŒããŠïŒãããã©ãŒãã³ã¹ã«åœ±é¿ããããããã調çããæ¹æ³ãããããŸããã
- èŸæž+ OneManyResourceLock ã ãªãã¿ãŒã¯ãèªã¿åã/æžã蟌ã¿ããã¯ãããã¹ãŠãçµãåºããããã§ãã ãã¹ãçµæã«ãããšãããã¯èŸæžã®æé䜿çšã§ãã ããããConcurrentDictionaryã¯ããã«é«éã§ãã
- ããã·ã¥ããŒãã« ã äºæ³ããã倱æã ããããç§ã¯ããã誀ã£ãŠäœ¿çšããŸããããä»ã®åå è
ã«å¹æµããçµæãåŸãããšãã§ãããšã¯æããŸããã ãšã«ãããäžè¬çã§ãªãã³ã¬ã¯ã·ã§ã³ãæ±ãã®ã¯ã©ããããããæ°ã®ãããããã§ããã
å
éšããã€ã¹ConcurrentDictionaryåè
ã詳ããèŠãŠã¿ãŸããããã€ãŸããConcurrentDictionaryã®ãœãŒã¹ãèŠãŠã¿ãŸãããã
ãã®ã¯ã©ã¹ãäœæãããšã
Capacityããã³
ConcurrencyLevelã® 2ã€ã®ãã©ã¡ãŒã¿ãŒãèšå®ãããŸãã æåã®ïŒ
Capacity ïŒã¯ã³ã¬ã¯ã·ã§ã³ã«éŠŽæã¿ããããå
éšã³ã¬ã¯ã·ã§ã³ãå±éããã«èšé²ã§ããèŠçŽ ã®æ°ãèšå®ããŸãã ãã®å Žåããªã³ã¯ããããªã¹ããäœæãããŸãïŒm_bucketsããã¹ã±ãããšåŒã°ããŸãïŒ ããã©ã«ãå€ã¯31ã§ãã
2çªç®ã®ãã©ã¡ãŒã¿ãŒïŒ
ConsurrencyLevel ïŒã¯ãèŸæžã«åæã«æžã蟌ãããšãã§ããã¹ã¬ããã®æ°ã決å®ããŸãã ããã¯ãã¢ãã¿ãŒã«ããããã¯çšã®ãªããžã§ã¯ãã®ã³ã¬ã¯ã·ã§ã³ãäœæããããšã«ããå®çŸãããŸãã ãã®ãããªåããããã³ã°ãªããžã§ã¯ãã¯ãã»ãŒåãæ°ã®ãã¹ã±ãããæ
åœããŸãã ããã©ã«ãå€ã¯Environment.ProcessorCount * 4ã§ãã
ãããã£ãŠããã£ã¯ã·ã§ããªå
ã®åãªããžã§ã¯ãã¯ããããååšãããã¹ã±ãããšæžã蟌ã¿çšã®ããã¯ãªããžã§ã¯ãã«äžæã«é¢é£ä»ããããŸãã ããã¯ãæ¬¡ã®æ¹æ³ã§è¡ãããŸãã
å¥åŠãªããšã«ãConcurrencyLevel = 1ã§ãã£ãŠããConcurrentDictionaryã¯éåžžã®ããã¯èŸæžãããé«éã§ãã ãŸããã¯ã©ã¹ãã€ãã¬ãŒã¿ãä»ããŠäœ¿çšããããã«æé©åãããŠããããšã泚ç®ã«å€ããŸãïŒãã¹ãã瀺ãããšããïŒã ç¹ã«ãToArrayïŒïŒã¡ãœãããåŒã³åºããšããã¹ãŠã®ãã¹ã±ããã§ããã¯ãå®è¡ãããã€ãã¬ãŒã¿ãŒãæ¯èŒçå®äŸ¡ã«äœ¿çšãããŸãã
äŸïŒdictionary.Values.ToArrayïŒïŒãããdictionary.SelectïŒx => x.ValueïŒ.ToArrayïŒïŒã䜿çšããããšããå§ãããŸãã
ãã®èšäºã¯ãå瀟ã®äžæµéçºè
ã«ãã£ãŠæžãããŸããã
ãæž
èŽããããšãããããŸããïŒ