ååã«èå³æ·±ãããæã«ã¯æ©ç¥ããã®ä»äºã¯ããã®çµæžå šäœãæé©åããããšã§ãã
顧客ã®ããŒãºã®é«ãŸãã¯ãå€ãã®å Žåãã·ã¹ãã ã®éã³ã³ããŒãã³ããããæ°ãããã®ã«åçŽã«çœ®ãæããããšãã§ããªãããšã«ããã£ãŠããŸãã ã³ã³ãã¥ãŒã¿ãŒã®ããã©ãŒãã³ã¹ãããŒããã©ã€ããšãããã¯ãŒã¯ã®èªã¿åã/æžã蟌ã¿é床ã¯ãã¯ã©ã€ã¢ã³ãã®èŠæ±ãããå€§å¹ ã«é ããªããŸãã
ã¯ã©ã¹ã¿ããŒãã®æ°ãå¢ããã®ã«åœ¹ç«ã€ããšã¯ãã£ãã«ãããŸããïŒéåžžãã·ã¹ãã ã¯åæ£ãããŠããŸãïŒã
å€ãã®å Žåããããã¡ã€ã©ãŒãå®è¡ããããã«ããã¯ãæ¢ãããœãŒã¹ã³ãŒãã«ç§»åããŠãååãæ®ããééããä¿®æ£ããå¿ èŠããããŸãã
åæã«é¢é£ããããã€ãã®åé¡ã«ã€ããŠã¯ãããã§èª¬æããŸãã ããã¯ãã«ãã¹ã¬ããããã°ã©ãã³ã°ã®å ¥éã³ãŒã¹ã§ã¯ãããŸãããèªè ãã¹ã¬ãããšã³ã³ããã¹ãã¹ã€ããã®æŠå¿µã«ç²ŸéããŠããããã¥ãŒããã¯ã¹ãã»ããã©ãªã©ã®çšéãç¥ã£ãŠããããšãåæãšããŠããŸãã
ãHello worldãããã倧ããªãã®ãèšèšãããã«ãã¹ã¬ããã®éçºè ã«ãšã£ãŠãå®å šã«éåæã®ã³ãŒããäœæããããšã¯éåžžã«é£ããããšã¯æããã§ããå ±éãã£ãã«ã«äœããæžããŠãã¡ã¢ãªå ã®æ§é ãå€æŽããå¿ èŠããããŸãïŒããšãã°ãããã·ã¥ããŒãã«ããªãŒãå転ãããŸãïŒãã¥ãŒãªã©ãã
ãã®ãããªã¢ã¯ã»ã¹ãåæããããšã«ãããã³ãŒãã®ããã€ãã®éèŠãªã»ã¯ã·ã§ã³ã®åæå®è¡ãå¶éããŸãã éåžžãããã¯1ã€ã§ããããŸãã«è€æ°ã®ã¹ã¬ããïŒ1ã©ã€ã¿ãŒ/ NãªãŒããŒãªã©ïŒã§ãã
åæã®å¿ èŠæ§ã¯åŠå®ã§ããŸããã é床ã®åæã¯éåžžã«æ害ã§ããããã°ã©ã ã®äžéšã¯2ã€ã3ã€ã®ã¹ã¬ããã§å€å°ã¹ããŒãã«åäœããŸãã
ãã ããå®éã«ã¯ãå®è¡ã®åæãäžååã§ãããšãåãçµæã«ãªãããšãããããšã瀺ãããŠããŸã-ã·ã¹ãã ã¯ã¹ãã£ãã¯ããŠããŸãã ããã¯ã䞊è¡ããŠå®è¡ãããã³ãŒãã«ãããšãã°ãHDDãžã®ã¢ã¯ã»ã¹ïŒé£ç¶ã·ãŒã¯ïŒãå«ãŸããå ŽåããŸãã¯è€æ°ã®å€§ããªã¡ã¢ãªãã£ã³ã¯ã«ã¢ã¯ã»ã¹ããå ŽåïŒããšãã°ãã³ã³ããã¹ãã¹ã€ããã§ãã£ãã·ã¥ã絶ãããªã»ãããã-CPUãã£ãã·ã¥ãæãã«èœã¡ãïŒã«çºçããŸãã
ã»ããã©ã䜿çšãã
ã»ããã©ã¯ãReadWriteMutexæ§é ãæ§ç¯ããããã ãã«çºæãããã®ã§ã¯ãããŸããã ã»ããã©ã¯ã䞊è¡ããŠå®è¡ãããã³ãŒãã®äžéšã§ããŒããŠã§ã¢ã®è² è·ã軜æžããããã«äœ¿çšã§ããŸãã
ååãšããŠãã³ãŒãããããã¡ã€ãªã³ã°ããããšã§ç°¡åã«èŠã€ããããšãã§ããå€ãã®ãã¹ãã£ãã¯ããæ²»ãããšãã§ããŸã-ã¹ã¬ããã®æ°ãå¢ãããšãåã ã®é¢æ°ã®å®è¡æéãèããå¢å ããä»ã®é¢æ°ã¯åããŸãã¯åçã®é床ã§åäœããŸãã
ãããã¡ã€ã©åºåãå±é
======================================================================================================================== Run # 1 (5 Threads) rpcsd (hbgsrv0189, PID:0718, TID:2648) # 03-09-2012 | 13:50:45 | Servlet: A::RpcsServlet, URI: /index-search ======================================================================================================================== NS | Name | C | T | Tot(s) | TwR(s) | Avg(s) | AwR(s) | Max(s) | Min(s) ======================================================================================================================== ::RPC::Service | service | 1 | 1 | 1.593 | 1.593 | 1.593 | 1.593 | 1.593 | 1.593 ::A::RpcsServlet | service | 1 | 1 | 1.592 | 1.592 | 1.592 | 1.592 | 1.592 | 1.592 ::IndexSrvRpc | index-search | 1 | 1 | 1.584 | 1.584 | 1.584 | 1.584 | 1.584 | 1.584 ::Indexer::Search | Search | 1 | 1 | 1.584 | 1.584 | 1.584 | 1.584 | 1.584 | 1.584 ::Indexer::Search | ParallelSearch | 2 | 2 | 1.256 | 1.256 | 0.628 | 0.628 | 0.655 | 0.601 ::Indexer::Search::Cache | SearchL2Index | 44 | 44 | 0.686 | 0.686 | 0.016 | 0.016 | 0.016 | 0.015 ::Indexer::Search | InvalidateCacheIdx | 20 | 20 | 0.570 | 0.570 | 0.028 | 0.028 | 0.031 | 0.020 ::Indexer::Search::Cache | InvalidateIdx | 20 | 20 | 0.276 | 0.276 | 0.014 | 0.014 | 0.016 | 0.002 ::Indexer::Search | SearchL1Index | 1 | 14 | 0.203 | 0.203 | 0.203 | 0.016 | 0.203 | 0.016 ::Indexer::Search | MergeJoin | 1 | 1 | 0.125 | 0.125 | 0.125 | 0.125 | 0.125 | 0.125 ======================================================================================================================== Run # 2 (25 Threads w/o semaphore) rpcsd (hbgsrv0189, PID:0718, TID:2648) # 03-09-2012 | 13:52:03 | Servlet: A::RpcsServlet, URI: /index-search ======================================================================================================================== NS | Name | C | T | Tot(s) | TwR(s) | Avg(s) | AwR(s) | Max(s) | Min(s) ======================================================================================================================== ::RPC::Service | service | 1 | 1 | 4.255 | 4.255 | 4.255 | 4.255 | 4.255 | 4.255 ::A::RpcsServlet | service | 1 | 1 | 4.254 | 4.254 | 4.254 | 4.254 | 4.254 | 4.254 ::IndexSrvRpc | index-search | 1 | 1 | 4.244 | 4.244 | 4.244 | 4.244 | 4.244 | 4.244 ::Indexer::Search | Search | 1 | 1 | 4.244 | 4.244 | 4.244 | 4.244 | 4.244 | 4.244 ::Indexer::Search | ParallelSearch | 2 | 2 | 3.729 | 3.729 | 1.865 | 1.865 | 1.889 | 1.840 ::Indexer::Search | InvalidateCacheIdx | 20 | 20 | 2.497 | 2.497 | 0.125 | 0.125 | 0.126 | 0.125 ::Indexer::Search::Cache | InvalidateIdx | 20 | 20 | 2.188 | 2.188 | 0.109 | 0.109 | 0.113 | 0.109 ::Indexer::Search::Cache | SearchL2Index | 44 | 44 | 1.231 | 1.231 | 0.028 | 0.028 | 0.031 | 0.015 ::Indexer::Search | SearchL1Index | 1 | 14 | 0.360 | 0.360 | 0.360 | 0.028 | 0.360 | 0.016 ::Indexer::Search | MergeJoin | 1 | 1 | 0.155 | 0.155 | 0.155 | 0.155 | 0.155 | 0.155 ======================================================================================================================== Run # 3 (25 Threads with semaphore in InvalidateCacheIdx, before InvalidateIdx) rpcsd (hbgsrv0189, PID:0718, TID:2648) # 03-09-2012 | 14:02:51 | Servlet: A::RpcsServlet, URI: /index-search ======================================================================================================================== NS | Name | C | T | Tot(s) | TwR(s) | Avg(s) | AwR(s) | Max(s) | Min(s) ======================================================================================================================== ::RPC::Service | service | 1 | 1 | 2.213 | 2.213 | 2.213 | 2.213 | 2.213 | 2.213 ::A::RpcsServlet | service | 1 | 1 | 2.213 | 2.213 | 2.213 | 2.213 | 2.213 | 2.213 ::IndexSrvRpc | index-search | 1 | 1 | 2.205 | 2.205 | 2.205 | 2.205 | 2.205 | 2.205 ::Indexer::Search | Search | 1 | 1 | 2.205 | 2.205 | 2.205 | 2.205 | 2.205 | 2.205 ::Indexer::Search | ParallelSearch | 2 | 2 | 1.690 | 1.690 | 0.845 | 0.845 | 0.889 | 0.801 ::Indexer::Search::Cache | SearchL2Index | 44 | 44 | 1.153 | 1.153 | 0.026 | 0.026 | 0.031 | 0.016 ::Indexer::Search | InvalidateCacheIdx | 20 | 20 | 0.537 | 0.537 | 0.027 | 0.027 | 0.031 | 0.007 ::Indexer::Search | SearchL1Index | 1 | 14 | 0.359 | 0.359 | 0.359 | 0.028 | 0.359 | 0.017 ::Indexer::Search::Cache | InvalidateIdx | 20 | 20 | 0.278 | 0.278 | 0.014 | 0.014 | 0.016 | 0.004 ::Indexer::Search | MergeJoin | 1 | 1 | 0.156 | 0.156 | 0.156 | 0.156 | 0.156 | 0.156
ãããã¡ã€ã©ãŒã®3çªç®ã®åé¡ã§ã¯ã
invCI_semaphore
ã»ããã©ã
InvalidateIdx
ã¡ãœããã®åŒã³åºãã«
invCI_semaphore
åŸã
InvalidateIdx
ã¡ãœããã®å®è¡æéããããã£ãŠ
InvalidateIdx
ã¡ãœãããã©ã®ããã«å€åãããã確èªã§ããŸãã
semaphore invCI_semaphore(config.InvCI_Count/* = 5*/); ... int InvalidateCacheIdx() { ... while (...) { cache.SearchL2Index(); invCI_semaphore++; while (cache.InvalidateIdx()) {}; invCI_semaphore--; } ... }
ã»ããã©ã䜿çšãããã®æ¹æ³ã¯éåžžã«åçŽã§ãããããã»ã¹ãå®å šã«ç解ããå¿ èŠã¯ãããŸãããã åãããã¯ã®ã¹ã¬ããã®æ倧æ°ãæŠéïŒå®çšŒåäžãã¯ã©ã€ã¢ã³ãã·ã¹ãã äžïŒã§éžæãããå¯èœæ§ãé«ããªã©ãå€ãã®æ¬ ç¹ããããŸããããé£ã¹ãŸãã ãããããã®æé©åæ¹æ³ã®å€§ããªå©ç¹ã¯ãå®è¡èšç»ãå€æŽããã«ããµãŒãã¹å šäœã®ã¹ã¬ããæ°ããã°ããå¢ããããšãã§ããããšã§ãã ãšã³ãžã³å šäœãã»ãšãã©å€æŽããããšãªããããã«ããã¯ã§ä»¥åã®å€ã«ããã€ãã®ã»ããã©ãé 眮ããã ãã§ãã ç§ã¯ã»ããã©ãèããã«äœ¿çšããããšãæ¯æããŠããŸããããäžæçãªè§£æ±ºçãšããŠïŒã¯ã©ã€ã¢ã³ããå®å¿ãããããïŒããã®ã¡ãœãããè€æ°å䜿çšããŠãåŸã§ãæ£ãããå·éã«ããçŽãããœãŒã¹ã³ãŒããæãäžããŸããã
åªå é äœãä»ãã
åªå 床ã¯éåžžã«äŸ¿å©ãªã¡ã«ããºã ã§ãããã¢ããªã±ãŒã·ã§ã³ããç°¡åã«ãæããããããšãã§ããŸãã ããšãã°ãã·ã¹ãã ãã°ãå¥ã®ã¹ããªãŒã ã«æžã蟌ãŸãããã®åªå 床ãæå°ã«äžãããšããã°ã¬ãã«ãäžããããšãªãããã»ã¹ãå€§å¹ ã«ãä¿é²ãã§ããŸãã
ããšãã°ãå€ãã®ã¹ã¬ãããæã€ããŒã«ãç°ãªãåªå 床ã®ã¿ã¹ã¯ãåŠçããå Žåã次ã®ã¿ã€ãã®èšèšã䜿çšã§ããŸãã
// before doing ... if ( thisThread.pool.count() > 1 && !(currentTaskType in (asap, immediately, now)) ) { thisThread.priority = 2 * thisThread.pool.priority; } else { thisThread.priority = 5 * thisThread.pool.priority; } // do current task ...
åæã«ãã¹ããªãŒã ã®åªå 床ã¯ããã®ã¹ããªãŒã ãååšããããŒã«ã ãã§ãªããããã»ã¹å šäœã§æå¹ã§ããããšãç解ããå¿ èŠããããŸãã泚æããŠäœ¿çšããŠãã ããã
Divide et imperaïŒåå²çµ±æ²»ïŒ
å€ãã®å Žåãã³ãŒããå³åº§ã«å®è¡ããå¿ èŠã¯ãããŸãã-ã€ãŸã äžéšã®ã¢ã¯ã·ã§ã³ãŸãã¯ã¿ã¹ã¯ã®äžéšã延æã§ããŸãã ããšãã°ããã°ã®æžã蟌ã¿ã蚪åæ°ã®ã«ãŠã³ãããã£ãã·ã¥ã®ã€ã³ããã¯ã¹ã®åäœæãªã©ã
åæã³ãŒããåå¥ã®ã¿ã¹ã¯ã«ãã€ã©ã€ãããåŸã§å®è¡ããïŒããšãã°ãããããããã¯ã°ã©ãŠã³ããµãŒãã¹ã䜿çšããïŒããšã«ãããå®è¡é床ãå€§å¹ ã«åäžãããããšãã§ããŸãã å¥ã®ã¹ã¬ãããã¹ã¬ããããŒã«ããŸãã¯å¥ã®RPCããã»ã¹ïŒWebServiceãžã®éåæåŒã³åºããªã©ïŒã§ããå ŽåããããŸãã åœç¶ããã®ã¿ã¹ã¯ã®åŒã³åºãïŒãã¥ãŒã€ã³ã°ãªã©ïŒã®æéã³ã¹ãã¯ãå®è¡èªäœã®ã³ã¹ããããå°ãããªããã°ãªããŸããã
å¥ã®LOGã¹ããªãŒã ã®äŸïŒ
// : int log(int level, ...) { if (level >= level2log) { logMutex.lock(); try { file.write(...); file.flush(); } finally { logMutex.release(); } } }
// - : int log(int level, ...) { if (level >= level2log) { // , : logQueue.mutex.lock(); logQueue.add(currentThread.id, ...); logQueue.mutex.release(); // -worker' : logQueue.threadEvent.pulse(); } } // background-logging thread: int logThreadProc() { ... while (true) { // - /* 500 ms */ /* 10 */: if ( logQueue.count < config.LogMaxCount /* = 10 */ || (sleepTime = currentTime - lastTime) < config.LogLatency /* = 500 */) { logQueue.threadEvent.wait(config.LogLatency - sleepTime); continue; }; // : logQueue.mutex.lock(); try { foreach (... in logQueue) { file.write(...); logQueue.delete(...); } } finally { logQueue.mutex.release(); } // : file.flush(); // : logQueue.threadEvent.wait(); lastTime = currentTime; } ... }
ãã®ãããªåçŽãªèšèšã«ããããã®ã³ã°ã®ã³ã¹ããå€§å¹ ã«åæžããã³ã³ããã¹ãåãæ¿ãã®çµæãåæžã§ããŸããããã¯ãå®éã«ã¯ã
log
ã¡ãœããã䜿çšããã¹ã¬ããã®æ°ã«äŸåããŸããã
ãã®ã³ã°ã«è¿œå ã®ããžãã¯ãæããŠããã°ã«çŽæ¥æžã蟌ãã¹ããªãŒã ã®ã¿ãããŒããããããšãç解ããããšãéèŠã§ãã ã€ãŸã ãã°ã奜ããªã ãã€ã³ããªãžã§ã³ãã«ããããšãã§ããŸã-LogLatencyã®æŠå¿µãå°å ¥ããäŸãšããŠãäœããã®çš®é¡ã®ãã°ã¢ãã©ã€ã¶ãŒïŒfail2banãªã©ïŒãè¿œå ãããããã¹ãŠã®ãããã°ã¡ãã»ãŒãžãä¿åããŠããšã©ãŒã®å Žåã«ã®ã¿ãã°ã«èšé²ããTIDããšã«ã°ã«ãŒãåããŸããªã© -ãããã¯ãã¹ãŠãå®éã«ã¯æ®ãã®ã¹ã¬ãããããŒãããŸããã
ããã«ãæåã®æ¹æ³ã䜿çšããå ŽåïŒã¡ãã»ãŒãžã¯ãã°ãã¡ã€ã«ã«çŽæ¥åæçã«æžã蟌ãŸããŸãïŒãã¹ã¬ããã¯ããããã䞊ååããããŸãã ã€ãŸã åæãªããžã§ã¯ãïŒãã¥ãŒããã¯ã¹ãã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ãåŸ æ©ã€ãã³ãïŒãå€ããªããã³ã³ããã¹ãã¹ã€ããã®ã³ã¹ããé«ããªãã»ã©ããããã®ãªããžã§ã¯ããééãããã¹ãŠã®ã¹ã¬ãããé çªã«å®è¡ãããå¯èœæ§ãé«ããªããŸãã
ã€ãŸã ã¿ã¹ã¯ã®ãã«ãã¹ã¬ããå®è¡ã®é床ã¯ãã·ã³ã°ã«ã¹ã¬ããå®è¡ã®é床ã«è¿ã¥ãããããã«æªåããŸãã ããã¯ïŒïŒãšãªãªãŒã¹ïŒïŒã®éã®æéãççž®ãããšãã³ãŒãã¯äžåºŠã«2æ¹åã«æ¹åãããŸããã¹ã¬ããèªäœã§éããªããããã»ã¹ã®ã䞊ååãã®å¯èœæ§ãæžå°ããŸãã
ã€ãã³ãã®ãã¥ãŒãæŽçãããšãè¿œå ã®ãããŒã®äœæã«é Œãããšãªããåæ§ã®æ§æãäœæã§ããå ŽåããããŸãã ããšãã°ãããã€ãã®ã¢ã¯ã·ã§ã³ããã¥ãŒã«å ¥ããŠãããšãã°ãã¢ã€ãã«æéãã®éã«ãåãã¹ã¬ããã§é çªã«å®è¡ããããã«ããŸãã
ããã¯ãTCLã§ç°¡åã«èª¬æã§ããŸãã
## / ... ... ## counter : set counter [db onecolumn {select cntr from accesslog where userid = $userid}] %> <%= $counter %> ... <% ## " access log" in background, "update idle": after idle UpdateAccess $userid [clock seconds] ## . .... ## - : proc UpdateAccess {userid lasttime} { db exec {update accesslog set cntr = cntr + 1, lastaccess = $lasttime where userid = $userid} }
ãã¥ãŒãFIFOãLIFOãããã³ãã«ãã¹ã¬ãã
ãã¥ãŒãããŒã¿ããŒã«ããŸãã¯ã·ãªã¢ã«ãããã¡ãŒãæŽçããããšã¯é£ããããšã§ã¯ãããŸãããããã«ãã¹ã¬ãããšãã®ä»ã®æ¡ä»¶ãåãå ŽåãLIFOãã¥ãŒã1çªç®ã®éžæè¢ã«ããå¿ èŠãããããšã«çæããå¿ èŠããããŸãïŒãã¡ãããã¢ã¯ã·ã§ã³ã®ã·ãŒã±ã³ã¹ãéèŠã§ãªãå ŽåïŒã LIFOãšFIFOãçµåãŸãã¯ã°ã«ãŒãåã§ããå ŽåããããŸãïŒLIFOèŠçŽ ãå°ããªFIFOãã¥ãŒã«ããããããšãã°æåŸãããããã¡ãŒãæ§ç¯ãããªã©ïŒã ãã®ãããªæªã¿ã®æå³ã¯ãããã»ããµãã£ãã·ã¥ã«ãããäžéšã¯ã¡ã¢ãªã®ä»®æ³ç·šæã«ãããŸãã ã€ãŸã LIFOã®æåŸã®èŠçŽ ããŸã ããã»ããµãã£ãã·ã¥ã«ãã確çã¯ãåãé·ãã®FIFOã®åãèŠçŽ ã®ç¢ºçãããæ¯èŒã«ãªããªãã»ã©é«ãã§ãã
å®äŸ-ç¬èªã®ã¡ã¢ãªãããŒãžã£ã§ã¯ãåããµã€ãºã®ããªãŒãªããžã§ã¯ãã®ããŒã«ããããã·ã¥ããŒãã«ãç·šæãããŸããïŒå€ãã®å Žåã
malloc
/
free
ãšåŒã°ãããããè¡ãããçç±ãç¥ã£ãŠããŸã:)ã ããŒã«ã¯FIFOã®ååã«åŸã£ãŠç·šæãããŸãã
mymalloc
é¢æ°ã¯ã
myfree
é¢æ°ã«ãã£ãŠããŒã«ã«å ¥ããããæåã®èŠçŽ ãè¿ããŸããã éçºè ã«FIFOã䜿çšããããã«ä¿ããçç±ã¯ããããªãã£ãŒã®ç¹ãŸã§åçŽã§ããäžéšã®æªæã®ãããããã°ã©ããŒãã
myfree
åŸã«
myfree
ãªããžã§ã¯ãã䜿çšããå Žåãããã°ã©ã ã¯ããããããé·ãåäœããŸãã LIFOã«çœ®ãæããåŸãã¡ã¢ãªãããŒãžã£ãŒãç©æ¥µçã«äœ¿çšããæŠåšåº«ïŒã¢ããªã±ãŒã·ã§ã³ãµãŒããŒïŒå šäœã§çŽ30ïŒ é«éåãããŸããã
ReadWriteMutex
å€ãã®å Žåãåæã¯ããªããžã§ã¯ããå€æŽãããå Žåã«ã®ã¿å¿ èŠã§ãã ããšãã°ãå ±æãã¡ã€ã«ã«æžã蟌ããšãããªã¹ããããã·ã¥ããŒãã«ã®æ§é ãå€æŽãããšããªã©ã åæã«ãååãšããŠãããã¯1ã€ã®ã¹ã¬ããã«ã®ã¿èš±å¯ãããŠãããå€ãã®å Žåãèªã¿åãã¹ã¬ããã§ãããããã¯ãããŸãïŒå€æŽã®çµãããŸã§ã®ãšã³ããªãå®å šã«æå¹ã§ã¯ãªããããããŒãã£ãŒèªã¿åããšäŸå€ã«ããããã°ã©ã ã¯ã©ãã·ã¥ãé€å€ããããïŒã
RW-mutexã䜿çšããŠãã®ãããªãªããžã§ã¯ããããã¯ãããšãèªã¿åãã¹ããªãŒã ãäºãã«ãããã¯ãããã¬ã³ãŒããããã¯ãããŠããå Žåã«ã®ã¿ã³ãŒããå®å šã«åæãããŸãïŒ1ã€ã®ã¹ã¬ããã§å®è¡ãããŸãïŒã
èªã¿åã/æžã蟌ã¿ãã¥ãŒããã¯ã¹ã䜿çšããå Žåã¯ããªããžã§ã¯ãã®èªã¿åãæ¹æ³ãåžžã«æ£ç¢ºã«ææ¡ããŠããå¿ èŠããããŸããèªã¿åãäžã§ãã£ãŠãããªããžã§ã¯ããå€æŽãããå Žåãããããã§ãïŒããšãã°ãåæåäžã«å éšãã£ãã·ã¥ãæ§ç¯ããå Žåãæžã蟌ã¿åŸã®ååæåäžïŒã ãã®å Žåãçæ³çãªAPIã¯ãããã¯ããã³ãŒã«ããã¯ãæäŸããŸãããã«ãã¹ã¬ããã®å Žåã¯åç¬ã§ãããã¯ããŸããRWãã¥ãŒããã¯ã¹ã®äœ¿çšã®å¯èœæ§ã«ã€ããŠã¯ããã¹ãŠã®äŸå€ãé€ããAPIããã¥ã¡ã³ãã§è©³ãã説æãããŠããŸãã äžéšã®RW-mutexå®è£ ã§ã¯ããªãŒããŒã¹ã¬ããïŒå Žåã«ãã£ãŠã¯ã©ã€ã¿ãŒã¹ã¬ããïŒã®æ°ãäºåã«ç¥ãå¿ èŠããããŸãïŒmutexã«äŒããïŒã ããã¯ãæžã蟌ã¿ããã¯ã®ç¹å®ã®å®è£ ã«ãããã®ã§ãïŒéåžžãã»ããã©ã䜿çšãããŸãïŒã ãããã®å¶éããã®ä»ã®å¶éã«ãããããããè€æ°ã®ãªãŒããŒã¹ããªãŒã ãããå Žåã¯ãå¯èœãªéãããã®ãããªãã¥ãŒããã¯ã¹ã§åæããããšããå§ãããŸãã
ããã¥ã¡ã³ããèªãã§ããœãŒã¹ã³ãŒããèªãã§ãã ãã
ç¹å®ã®ã¯ã©ã¹ãŸãã¯ãªããžã§ã¯ãã®èåŸã«é ãããŠãããã®ã®ç¡ç解ãæã«ã¯èª€è§£ã®åé¡ã¯ããã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšããå Žåã«ç¹ã«éèŠã§ãã ããã¯ãåºæ¬çãªåæãªããžã§ã¯ãã«ç¹ã«åœãŠã¯ãŸããŸãã RW-mutexã®äžé©åãªäœ¿çšã®äŸã«ãã£ãŠãç§ãæå³ããããšãæ確ã«ããããšããŸãã
ç§ã®ååã®äžäººã¯ããã€ãŠã»ããã©äžã«æ§ç¯ãããå ¬æ£ãªRWãã¥ãŒããã¯ã¹ã䜿çšããŠããŸããã 圌ã¯ããªãŒããŒã¹ããªãŒã ã®æ°ãRWMutexã¯ã©ã¹ã«åçã«è»¢éããã®ãé¢åã§ïŒéçã«ãå¯èœãªæ倧ãå€ã500ã«èšå®ïŒãã©ã€ã¿ãŒã¹ããªãŒã ã«æ¬¡ã®ã³ãŒããèšè¿°ããŸããã
... RWMutex mtx(500); ... mtx.lockWrite(); hashTab.add(...); mtx.releaseWrite(); ...
ãããŠãè² è·ã
void RWMutex::lockWrite() { writeMutex.lock(); for (register int i = 0; i < readersCount /* 500 */; i++) readSemaphore++; } void RWMutex::releaseWrite() { if (!f4read) writeMutex.release(); readSemaphore -= readersCount; if (f4read) writeMutex.release(); }
ãã®èšèšã§ã¯ã
readSemaphore += readersCount
ã§ã¯ãªãã
lockWrite
æ¬äœã®ã«ãŒãã§
readSemaphore++
ã€ã³ã¯ãªã¡ã³ãã䜿çšããŠããããããªãŒããŒã¹ããªãŒã ãšã©ã€ã¿ãŒã¹ããªãŒã ã®æ©äŒãçãããªããŸãã ãããã圌ã¯ããã®RWMutexãæ§ç¯ããããã®ã»ããã©ã¯ã©ã¹ã1ã€ã®ã¯ãã¹ãã©ãããã©ãŒã ã©ã€ãã©ãªã䜿çšããŠããããšãç¥ããªãã£ãããããã®ç¹å®ã®ãã©ãããã©ãŒã çšã«æ¬¡ã®ãããªåçŽãªã³ãŒããçæãããŸããã
int Semaphore::operator ++() { mutex.lock(); if (sema++ > MaxFlowCount) flowMutex.lock(); mutex.release(); }
ã€ãŸã
hashTab
ããã·ã¥ããŒãã«ã«100åã®å€ãè¿œå ãããè€æ°ã®ãªãŒããŒã¹ã¬ããã«ãã£ãŠåæã«èªã¿åãããå Žåã100 * 500ã®ããã¯ãçºçããŸããïŒã³ã³ããã¹ãã®åãæ¿ãã«ããæ°ããªç§ãçºçããŸããïŒã ãã®ã¹ããŒãªãŒã§æãèå³æ·±ãã®ã¯ããããããŒã¹ã¯ã©ã¹RWSyncHashTableã§ãããã³ãŒãã®ããããå Žæã§ç©æ¥µçã«äœ¿çšãããŠããããšã§ãã
çæããŠãã ããïŒäžéšã®APIã³ã³ã¹ãã©ã¯ãã¯æ¢ã«åæããŠããå ŽåããããŸãã å Žåã«ãã£ãŠã¯ããªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãšãã¹ãã©ã¯ã¿ã§ãããããŸãã ãã®å Žåãè¿œå ã®åæã¯å€ãã®å Žåæ害ã§ãã ããã¯ããterããã¿ãŒã§å°ç¡ãã«ãããšãã ãã§ãã
ãœãŒã¹ãèªãã§ãAPIã®ããã¥ã¡ã³ããèŠãŠãã ãã-ãããŠããã®ãããªééãã¯ããªããè¿åããå¯èœæ§ãé«ãã§ãã
åæïŒ=åŸ æ©äž
å®è¡ã®åæã¯ãããã»ã¹ãåŸ æ©ããããšã ããè¡ãããšãæå³ãããã®ã§ã¯ãããŸããã ææ°ã®ã·ã¹ãã ã®ãããã¯æ¹æ³ã¯éåžžã«æè»ã§ããã次ã®èšèšãè¡ãããšãã§ããŸãã
static int mtx_locked = 0; // - - , 1 ? while ( mtx_locked || !mtx.lock(config.MaxWaitTime /* 1 ms */) ) { // - - ... ... processNextRequest(); } // - ... mtx_locked++; // ... processInLock(); // unlock ... mtx_locked--; mtx.release();
ãã®çš®ã®ã³ãŒãã䜿çšãããšããã¥ãŒããã¯ã¹ãããã¯ãããŠå°±å¯ããã®ãåŸ ã€ã®ã§ã¯ãªããçŸæç¹ã§å¥ã®ããšãããããšããããšãã§ããŸãã åæ§ã®ååã«åºã¥ããŠãå®è£ æ¹æ³ã¯å°ãç°ãªããŸããïŒã³ãŒã«ããã¯ãŸãã¯ã€ãã³ãã®å®è¡ããã©ã³ã¶ã¯ã·ã§ã³ã®åŸ æ©ããã¯ãã¹ã¬ãããã£ãã·ã¥ããšãªã©ïŒãéåæããã°ã©ãã³ã°ã®æŠå¿µãããŒã¹ã«ãªã£ãŠããŸãã ãã®å Žåãéåžžã«åçŽãªã«ãŒã«ãåŸ ããªãã§ãã ãããã«åŸãå¿ èŠããããŸãã
ãã®äŸã¯ãã³ã³ããã¹ãã¹ã€ãããåé¿ãŸãã¯æå°åãããã1ã€ã®ããªãã¯ã瀺ããŠããŸããããã¯éçå€æ°
mtx_locked
ã§ãã ãã®ææ³ã«ãããã³ãŒãããããã¯ãã
mtx.lock
ããããšãäºåã«ããã£ãŠããå ŽåïŒ
mtx_locked > 0
ïŒã
mtx_locked > 0
ãå®è¡ã§ããªããªããŸãã確å®ã«ç¥ãå¿ èŠã¯ãããŸãããä»ã®ããšãè¡ãã ãã§ãã
ããããæåã®éšåïŒå€ãã®æçŽïŒãçµãã䟡å€ããããŸãã 誰ãã®ããã«ç§ãã©ããã§éèŠãªçå®ãæžãããªããæªããã§ã¯ãªããåŸé ã«ç§ãèš±ããŠãã ããã ææ¡ãåžæãæ¹å€ãæè¿ããŸãã
次ã®ããŒãã§ã¯ïŒ
- ãããããã¯
- ã€ãã³ã åŸ æ©äžã®åå¿;
- ããŒã¿ãã³ã¯ã®åæã
- ã·ã¹ãã å šäœã®åæïŒã¯ãã¹ããã»ã¹ãã¯ãã¹ã¯ã©ã¹ã¿ãŒïŒ
- éåæããã°ã©ãã³ã°ã
- å ±æãªãœãŒã¹
- ãã¿ããªãœãŒã¹ã®è§£æŸ
- ã¹ããªãŒã ç£èŠãHeartBit
- ãããã¡ã€ãªã³ã°
- ããªãã®é¡ã