int n=10的sizeof 为什么是四_mongodb内核源码实现、性能调优( 六 )


线程主循环主要工作内容:1. 从ASIO库的全局队列获取任务执行;2. 判断本线程是否比较”闲”,如果是则直接销毁退出 。3. 线程创建起来进行初始线程名设置、线程主循环一些计数处理等 。
3.2.3控制线程核心代码实现
控制线程用于判断线程池是线程是否压力很大,是否比较”忙”,如果是则增加线程数来减轻全局队列中task 任务积压引起的延迟处理问题 。控制线程核心代码实现如下:
1. //controller控制线程2. void ServiceExecutorAdaptive::_controllerThreadRoutine() {3.//控制线程线程名设置4.setThreadName("worker-controller"_sd);5.......6.//控制线程主循环7.while (()) {8.//一次while结束的时候执行对应func ,也就是结束的时候计算为起始时间9.const auto timerResetGuard =10.MakeGuard([&sinceLastControlRound] { (); });11.//等待工作线程通知,最多等待stuckThreadTimeout12.(fakeLk, _config->stuckThreadTimeout().toSystemDuration());13.......14.double utilizationPct;15.{16.//获取所有线程执行任务的总时间17.auto spentExecuting = _getThreadTimerTotal(ThreadTimer::Executing);18.//获取所有线程整个生命周期时间(包括空闲时间+执行任务时间+创建线程的时间)19.auto spentRunning = _getThreadTimerTotal(ThreadTimer::Running);20.//也就是while中执行一次这个过程中spentExecuting差值,21.//也就是spentExecuting代表while一次循环的Executing time开始值,22.//lastSpentExecuting代表一次循环对应的结束time值23.auto diffExecuting = spentExecuting - lastSpentExecuting;24.//也就是spentRunning代表while一次循环的running time开始值,25.//lastSpentRunning代表一次循环对应的结束time值26.auto diffRunning = spentRunning - lastSpentRunning;27.if (spentRunning == 0 || diffRunning == 0)28.utilizationPct =29.else {30.lastSpentExecuting = spentExecuting;31.lastSpentRunning = spentRunning;32.33.//一次while循环过程中所有线程执行任务的时间和线程运行总时间的比值34.utilizationPct = diffExecuting / static_cast(diffRunning);35.utilizationPct *= 100;36.}37.}38.//也就是本while()执行一次的时间差值,也就是上次走到这里的时间和本次走到这里的时间差值大于该阀值39.//也就是控制线程太久没有判断线程池是否够用了40.if (() >= _config->stuckThreadTimeout()) {41.//use中的线程数=线程池中总的线程数,说明线程池中线程太忙了42.if ((() == ()) &&43.(sinceLastSchedule >= _config->stuckThreadTimeout())) {44.log() << "Detected blocked worker threads, "45.<< "starting new reserve threads to unblock service executor";46.//一次批量创建这么多线程,如果我们配置adaptiveServiceExecutorReservedThreads非常大47.//这里实际上有个问题,则这里会一次性创建非常多的线程,可能反而会成为系统瓶颈48.//建议mongodb官方这里最好做一下上限限制49.for (int i = 0; i < _config->reservedThreads(); i++) {50.//创建新的worker工作线程51._startWorkerThread();52.}53.}54.continue;55.}56.//当前的worker线程数57.auto threadsRunning = ();58.//保证线程池中worker线程数最少都要reservedThreads个59.if (threadsRunning < _config->reservedThreads()) {60.//线程池中线程数最少数量不能比最低配置少61.while (() < _config->reservedThreads()) {62._startWorkerThread();63.}64.}65.//worker线程非空闲占比小于该阀值,说明压力不大,不需要增加worker线程数66.if (utilizationPct < _config->idlePctThreshold()) {67.continue;68.}69.//走到这里,说明整体worker工作压力还是很大的70.//我们在这里循环stuckThreadTimeout毫秒,直到我们等待worker线程创建起来并正常运行task71.//因为如果有正在创建的worker线程,我们等待一小会,最多等待stuckThreadTimeout ms72.//保证一次while循环时间为stuckThreadTimeout73.do {74.stdx::this_thread::sleep_for(_config->maxQueueLatency().toSystemDuration());75.} while ((() > 0) &&76.(()