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

< _config->recursionLimit())) {46.//本线程立马直接执行wrappedTask任务,不用入队到boost-asio全局队列等待调度执行47.//io_context::dispatchio_context::dispatch48._ioContext->dispatch(std::move(wrappedTask));49.} else { //入队io_context::post50.//task入队到schedule得全局队列,等待工作线程调度51._ioContext->post(std::move(wrappedTask));52.}53.//54.();55.//总的入队任务数56.(1);57.//kDeferredTask真正生效在这里58.//如果队列中的任务数大于可用线程数,说明worker压力过大,需要创建新的worker线程59.if (_isStarved() && !(flags & kDeferredTask)) {//kDeferredTask真正生效在这里60.//条件变量,通知controler线程,通知_controllerThreadRoutine控制线程处理61.();62.}63.return Status::OK();}
从上面的分析可以看出,() 主要完成task任务入队处理 。如果带有递归标识,则通过->() 接口入队,该接口再ASIO底层实现的时候实际上没有真正把任务添加到全局队列,而是直接当前线程继续处理,这样就实现了递归调用 。如果没有携带递归标识,则task 任务通过->post() 需要入队到全局队列 。ASIO库的接口和post接口的具体实现可以参考:
如果任务入队到全局队列,则线程池中的 线程就会通过全局锁竞争从队列中获取task任务执行,该流程通过如下接口实现:
1. //创建线程的回掉函数,线程循环主体,从队列获取task任务执行2. void ServiceExecutorAdaptive::_workerThreadRoutine(3.int threadId, ServiceExecutorAdaptive::ThreadList::iterator state) {4.//设置线程模5._localThreadState = &(*state);6.{7.//worker-N线程名8.std::string threadName = str::stream() << "worker-" << threadId;9.setThreadName(threadName);10.}11.//该线程第一次执行while中的任务的时候为ture,后面都是false12.//表示该线程是刚创建起来的,还没有执行任何一个task13.bool stillPending = true;14.15.//线程退出的时候执行以下{},都是一些计数清理16.const auto guard = MakeGuard([this, &stillPending, state] {17.//该worker线程退出前的计数清理、信号通知处理18.//......19.}20.while (()) {21.......22.//本次循环执行task的时间,不包括网络IO等待时间23.state->executingCurRun = 0;24.try {25.//通过_ioContext和入队的任务联系起来26.asio::io_context::work work(*_ioContext);27.//记录开始时间,也就是任务执行开始时间28.state->();29.//执行ServiceExecutorAdaptive::schedule中对应的task30.//线程第一次运行task任务,最多从队列拿一个任务执行31.//()指定一次run最多运行多长时间32.if (stillPending) {33.//执行一个任务就会返回34._ioContext->run_one_for(());35.} else {// Otherwise, just run for the full run period36.//_ioContext对应的所有任务都执行完或者toSystemDuration超时后才会返回37._ioContext->run_for(()); //io_context::run_for38.}39.......40.}41.//该线程第一次执行while中的任务后设置ture,后面都是false42.if (stillPending) {43.(1);44.stillPending = false;45.//当前线程数比初始线程数多46.} else if (() > _config->reservedThreads()) {47.//代表本次循环该线程真正处理任务的时间与本次循环总时间(总时间包括IO等待和IO任务处理时间)48.double executingToRunning = state->executingCurRun / static_cast(spentRunning);49.executingToRunning *= 100;50.dassert(executingToRunning <= 100);51.52.int pctExecuting = static_cast(executingToRunning);53.//线程很多,超过了指定配置,并且满足这个条件,该worker线程会退出,线程比较空闲,退出54.//如果线程真正处理任务执行时间占比小于该值,则说明本线程比较空闲,可以退出 。55.if (pctExecuting < _config->idlePctThreshold()) {56.log() << "Thread was only executing tasks " << pctExecuting << "% over the last "57.<< runTime << ". Exiting thread.";58.break;//退出线程循环,也就是线程自动销毁了59.}60.}61.}62. }