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


工作线程启动后的时间可以包含两类:1. 线程运行task任务的时间;2.线程等待客户端请求的时间 。一个线程创建起来,如果没有客户端请求,则线程就会等待接收数据 。如果有客户端请求,线程就会通过队列获取task任务运行 。这两类时间分别代表线程”忙”和“空闲” 。
线程总的“忙”状态时间 =所有线程运行task任务的时间,包括已经销毁的线程 。线程总的“空闲”时间=所有线程等待获取任务执行的时间,也包括已销毁的线程,线程空闲一般是没有客户端请求,或者客户端请求很少 。工作线程对应while(){}循环每循环一次都会进行线程私有运行时间计数,总的时间统计就是以该线程私有统计信息为基准求和而来 。
.2工作线程创建、销毁及task任务处理
工作线程在如下情况下创建或者销毁:1. 线程池初始化;2. 控制线程发现当前线程池中线程比较”忙”,则会动态创建新的工作线程;3. 工作线程在while体中每循环一次都会判断当前线程池是否很”闲”,如果很”闲”则本线程直接销毁退出 。
工作线程创建核心源码实现如下:
1. Status ServiceExecutorAdaptive::start() {2.invariant(!());3.//running状态4.(true);5.//控制线程初始化创建,线程回调ServiceExecutorAdaptive::_controllerThreadRoutine6._controllerThread = stdx::thread(&ServiceExecutorAdaptive::_controllerThreadRoutine, this);7.//启动时候默认启用CPU核心数/2个worker线程8.for (auto i = 0; i < _config->reservedThreads(); i++) {9.//创建一个工作线程10._startWorkerThread();11.}12.return Status::OK();13. }
工作线程默认初始化为CPU/2个,初始工作线程数也可以通过指定的命令行参数来配置: 。此外,start()接口默认也会创建一个控制线程 。
Task 任务通过SSM状态机调用ive::() 接口入队,该函数接口核心代码实现如下:
1. Status ServiceExecutorAdaptive::schedule(ServiceExecutorAdaptive::Task task, ScheduleFlags flags) {2.//获取当前时间3.auto scheduleTime = _tickSource->getTicks();4.//kTasksQueued: 普通tak,也就是dealTask5.//_deferredTasksQueued: deferred task,也就是readTask6.//defered task和普通task分开记录_totalQueued=_deferredTasksQueued+_tasksQueued7.auto pendingCounterPtr = (flags & kDeferredTask) ? &_deferredTasksQueued : &_tasksQueued;8.//相应队列9.pendingCounterPtr->addAndFetch(1);10.......11.//这里面的task()执行后-task()执行前的时间才是CPU真正工作的时间12.auto wrappedTask = [ this, task = std::move(task), scheduleTime, pendingCounterPtr ] {13.//worker线程回调会执行该wrappedTask,14.pendingCounterPtr->subtractAndFetch(1);15.auto start = _tickSource->getTicks();16.//从任务被调度入队,到真正被执行这段过程的时间,也就是等待被调度的时间17.//从任务被调度入队,到真正被执行这段过程的时间18.(start - scheduleTime);19.//recursionDepth=0说明开始进入调度处理,后续有可能是递归执行20.if (_localThreadState->recursionDepth++ == 0) {21.//记录wrappedTask被worker线程调度执行的起始时间22._localThreadState->();23.//当前正在执行wrappedTask的线程加124.(1);25.}26.//ServiceExecutorAdaptive::_workerThreadRoutine执行wrappedTask后会调用guard这里的func27.const auto guard = MakeGuard([this, start] { //改函数在task()运行后执行28.//每执行一个任务完成,则递归深度自减29.if (--_localThreadState->recursionDepth == 0) {30.//wrappedTask任务被执行消耗的总时间31.//_localThreadState->()代表任务该task执行的时间32._localThreadState->executingCurRun += _localThreadState->();33.//下面的task()执行完后,正在执行task的线程-134.(1);35.}36.//总执行的任务数,task每执行一次增加一次37.(1);38.});39.//运行任务40.task();41.};42.//kMayRecurse标识的任务,会进行递归调用dealTask进入调度的时候调由该标识43.if ((flags & kMayRecurse) && //递归调用,任务还是由本线程处理44.//递归深度还没达到上限,则还是由本线程继续调度执行wrappedTask任务45.(_localThreadState->recursionDepth + 1