test_threadPool&test_threadPoolBenchmark 分析
1.类图
2.代码注释:
2.1 test_threadPool.cpp
1 /** 2 * 演示功能说明: 3 * 1.线程池异步运行 “X = cpu逻辑核个数*4” 个任务,每个任务执行 task_second = 3秒 4 * 2.使用Ticker计时 X个任务执行消耗的时间 5 * 3.vec存放执行任务的顺序编号 i 6 * 4.linux /mac系统会设置cpu的亲和性 7 * 5.使用信号量 sem 进行进程控制 8 */ 9 int main() { 10 //初始化日志系统 11 Logger::Instance().add(std::make_shared<ConsoleChannel>()); 12 Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>()); 13 //liu 此笔记本的逻辑处理器是12个 14 ThreadPool pool(thread::hardware_concurrency(), ThreadPool::PRIORITY_HIGHEST, true); 15 16 //每个任务耗时3秒 17 auto task_second = 3; 18 // liu 返回支持的并发线程数 https://zh.cppreference.com/w/cpp/thread/thread/hardware_concurrency 19 //每个线程平均执行4次任务,总耗时应该为12秒 20 auto task_count = thread::hardware_concurrency() * 4; 21 22 semaphore sem; 23 //liu vec中存放的是已经执行的任务的编号 i 24 vector<int> vec; 25 // liu 重设容器大小以容纳 count 个元素 26 vec.resize(task_count); 27 Ticker ticker; 28 { 29 //放在作用域中确保token引用次数减1 30 auto token = std::make_shared<onceToken>(nullptr, [&]() { 31 // liu v操作 释放资源 加1 32 sem.post(); 33 }); 34 35 // liu 异步执行48个任务 36 for (auto i = 0; i < task_count; ++i) { 37 pool.async([token, i, task_second, &vec]() { 38 setThreadName(("thread pool " + to_string(i)).data()); 39 std::this_thread::sleep_for(std::chrono::seconds(task_second)); //休眠三秒 40 InfoL << "task " << i << " done!"; 41 vec[i] = i; 42 }); 43 } 44 } 45 46 //liu p操作 申请资源 减1 47 sem.wait(); 48 InfoL << "all task done, used milliseconds:" << ticker.elapsedTime(); 49 50 //打印执行结果 51 for (auto i = 0; i < task_count; ++i) { 52 InfoL << vec[i]; 53 } 54 return 0; 55 }
2.2 threadPool.h
1 /* 2 * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved. 3 * 4 * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit). 5 * 6 * Use of this source code is governed by MIT license that can be found in the 7 * LICENSE file in the root of the source tree. All contributing project authors 8 * may be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef THREADPOOL_H_ 12 #define THREADPOOL_H_ 13 14 #include "threadgroup.h" 15 #include "TaskQueue.h" 16 #include "TaskExecutor.h" 17 #include "Util/util.h" 18 #include "Util/logger.h" 19 20 namespace toolkit { 21 22 /** 23 * liu 24 * 理解到关键点: 25 * thread_group 管理thread 26 * TaskQueue<Task::Ptr> _queue:管理任务 27 * 任务需要扔到thread中运行 28 */ 29 class ThreadPool : public TaskExecutor { 30 public: 31 //liu 在ThreadPool构造函数中,默认设置最高优先级PRIORITY_HIGHEST 32 enum Priority { 33 PRIORITY_LOWEST = 0, 34 PRIORITY_LOW, 35 PRIORITY_NORMAL, 36 PRIORITY_HIGH, 37 PRIORITY_HIGHEST 38 }; 39 40 /** 41 * liu 构造函数: 42 * 1.创建线程池对象,开辟线程,并且运行线程 43 * 2.设置cpu亲和性,提高命中率,目前设置的都是index = 0 44 * 3.构造函数执行中,已经创建了线程,然后放到thread_group中,并且每个线程开始逐个run() 45 * 4.【关键点】管理线程池ThreadPool中的 thread,记录 以thread_id为键,thread对象为值 46 * thread_group _thread_group; 47 * 5.【关键点】Task异步任务存放容器,作为缓存,最后任务都得从队列中取出来,在thread中进行执行run; 48 * TaskQueue<Task::Ptr> _queue; 49 * @param num 线程池开辟的线程个数 50 * @param priority 线程池的优先级 51 * @param auto_run 是否同步开始运行 52 * @param set_affinity 是否设置亲和性,亲和性只设置取模: index % cpu逻辑核数 53 * @param pool_name 线程池的名称 54 */ 55 ThreadPool(int num = 1, Priority priority = PRIORITY_HIGHEST, bool auto_run = true, bool set_affinity = true, 56 const std::string &pool_name = "thread pool") { 57 _thread_num = num; 58 _on_setup = [pool_name, priority, set_affinity](int index) { 59 std::string name = pool_name + ' ' + std::to_string(index); 60 setPriority(priority); 61 setThreadName(name.data()); 62 if (set_affinity) { // liu win-debug调试 index = 0/ ubuntu-debug index = 0 63 setThreadAffinity(index % std::thread::hardware_concurrency()); 64 } 65 }; 66 _logger = Logger::Instance().shared_from_this(); 67 if (auto_run) { 68 start(); 69 } 70 } 71 72 ~ThreadPool() { 73 shutdown(); 74 wait(); 75 } 76 77 /** 78 * liu 从TaskExecutorInterface 继承来的方法 79 * @param task 80 * @param may_sync 81 * @return 82 */ 83 //把任务打入线程池并异步执行 84 Task::Ptr async(TaskIn task, bool may_sync = true) override { 85 if (may_sync && _thread_group.is_this_thread_in()) { 86 // liu 生成该Task的对象,调用构造函数 87 task(); 88 return nullptr; 89 } 90 auto ret = std::make_shared<Task>(std::move(task)); 91 // liu 任务插入到TaskQueue(list)的back 92 _queue.push_task(ret); 93 return ret; 94 } 95 96 // liu 任务插入到TaskQueue(list)的front 97 Task::Ptr async_first(TaskIn task, bool may_sync = true) override { 98 if (may_sync && _thread_group.is_this_thread_in()) { 99 task(); 100 return nullptr; 101 } 102 103 auto ret = std::make_shared<Task>(std::move(task)); 104 _queue.push_task_first(ret); 105 return ret; 106 } 107 108 size_t size() { 109 return _queue.size(); 110 } 111 112 /** 113 * liu 设置线程池优先级 114 * @param priority 115 * @param threadId std::thread::native_handle 返回实现定义的底层线程柄 116 * 【参考: https://zh.cppreference.com/w/cpp/thread/thread/native_handle】 117 * 【参考:重要文章】https://blog.csdn.net/super828/article/details/118683784 118 * 返回表示的线程句柄的特定于实现的类型。 特定于实现的方式,可以使用的线程句柄 119 * 【参考:https://learn.microsoft.com/zh-cn/previous-versions/jj870808(v=vs.140)】 120 * 获取当前线程的线程id,一般就是std::thread提供的接口不满足要求时,需要获取线程id调用底层库进行操作 121 * 【参考:https://zhuanlan.zhihu.com/p/547970094】 122 * @return 123 */ 124 static bool setPriority(Priority priority = PRIORITY_NORMAL, std::thread::native_handle_type threadId = 0) { 125 // set priority 126 #if defined(_WIN32) 127 static int Priorities[] = { THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST }; 128 if (priority != PRIORITY_NORMAL && SetThreadPriority(GetCurrentThread(), Priorities[priority]) == 0) { 129 return false; 130 } 131 return true; 132 #else 133 static int Min = sched_get_priority_min(SCHED_FIFO); 134 if (Min == -1) { 135 return false; 136 } 137 static int Max = sched_get_priority_max(SCHED_FIFO); 138 if (Max == -1) { 139 return false; 140 } 141 142 // liu ubuntu20.01 clion-debug 143 // Priorities[] = {1,25,50,74,99}; max = 99; min = 1 144 static int Priorities[] = {Min, Min + (Max - Min) / 4, Min + (Max - Min) / 2, Min + (Max - Min) * 3 / 4, Max}; 145 146 if (threadId == 0) { 147 threadId = pthread_self(); 148 } 149 struct sched_param params; 150 params.sched_priority = Priorities[priority]; 151 // liu params.sched_priority = {int}99 152 return pthread_setschedparam(threadId, SCHED_FIFO, ¶ms) == 0; 153 #endif 154 } 155 156 /** 157 * liu 158 * 1.创建线程,然后放到thread_group中 159 * 2.并且开始执行thread.run 线程运行,调用了该类成员函数 run(index i) 160 */ 161 void start() { 162 if (_thread_num <= 0) { 163 return; 164 } 165 size_t total = _thread_num - _thread_group.size(); 166 for (size_t i = 0; i < total; ++i) { 167 _thread_group.create_thread([this, i]() {run(i);}); 168 } 169 } 170 171 private: 172 // liu 循环while不停的取出任务容器_queue中的Task任务,不停的执行任务 173 void run(size_t index) { 174 _on_setup(index); 175 Task::Ptr task; 176 while (true) { 177 startSleep(); 178 //liu此task的来源是 async 放入到thread_group对象中的_threads(map)中的对象 179 // 所有已经创建的线程都在 _threads 中,map,以thread_id为键,thread对象为值 180 if (!_queue.get_task(task)) { 181 //空任务,退出线程 182 break; 183 } 184 sleepWakeUp(); 185 // liu 执行task 186 try { 187 (*task)(); 188 task = nullptr; 189 } catch (std::exception &ex) { 190 ErrorL << "ThreadPool catch a exception: " << ex.what(); 191 } 192 } 193 } 194 195 void wait() { 196 _thread_group.join_all(); 197 } 198 199 void shutdown() { 200 _queue.push_exit(_thread_num); 201 } 202 203 private: 204 size_t _thread_num; 205 Logger::Ptr _logger; 206 // liu 【关键点】管理线程池ThreadPool的 thread; 207 thread_group _thread_group; 208 // liu 【关键点】Task异步任务存放容器,作为缓存,最后任务都得从队列中取出来,在thread中进行执行run; 209 TaskQueue<Task::Ptr> _queue; 210 /*类模板 std :: function 是一个通用的多态函数包装器。 211 * std :: function 的实例可以存储,复制和调用任何可调用的目标 :包括函数,lambda表达式,绑定表达式或其他函数对象,以及指向成员函数和指向数据成员的指针。 212 * 当std::function对象未包裹任何实际的可调用元素,调用该 std::function 对象将抛出std::bad_function_call 异常。 213 * 原文链接:https://blog.csdn.net/qq_41317716/article/details/125839126*/ 214 std::function<void(int)> _on_setup; 215 }; 216 217 } /* namespace toolkit */ 218 #endif /* THREADPOOL_H_ */
2.3 threadgroup.h
1 /* 2 * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved. 3 * 4 * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit). 5 * 6 * Use of this source code is governed by MIT license that can be found in the 7 * LICENSE file in the root of the source tree. All contributing project authors 8 * may be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef THREADGROUP_H_ 12 #define THREADGROUP_H_ 13 14 #include <stdexcept> 15 #include <thread> 16 #include <unordered_map> 17 18 namespace toolkit { 19 20 /** 21 * liu 22 * 1.所有已经创建的线程都在 _threads 中,map,以thread_id为键,thread对象为值 23 * 2.赋值和拷贝构造函数是private权限 24 */ 25 class thread_group { 26 private: 27 // liu 拷贝构造 28 thread_group(thread_group const &); 29 // liu 赋值构造 30 thread_group &operator=(thread_group const &); 31 32 public: 33 thread_group() {} 34 35 ~thread_group() { 36 _threads.clear(); 37 } 38 39 40 // liu 判断该this指向的线程是否在该thread_group中 41 bool is_this_thread_in() { 42 auto thread_id = std::this_thread::get_id(); 43 if (_thread_id == thread_id) { 44 return true; 45 } 46 return _threads.find(thread_id) != _threads.end(); 47 } 48 49 //liu 判断该线程thread是否在thread_group中 50 bool is_thread_in(std::thread *thrd) { 51 if (!thrd) { 52 return false; 53 } 54 auto it = _threads.find(thrd->get_id()); 55 return it != _threads.end(); 56 } 57 58 //liu 将线程对象放入到_threads(map)中:thread_id 是键,thread对象是值 59 template<typename F> 60 std::thread *create_thread(F &&threadfunc) { 61 auto thread_new = std::make_shared<std::thread>(threadfunc); 62 _thread_id = thread_new->get_id(); 63 _threads[_thread_id] = thread_new; 64 return thread_new.get(); 65 } 66 67 void remove_thread(std::thread *thrd) { 68 auto it = _threads.find(thrd->get_id()); 69 if (it != _threads.end()) { 70 _threads.erase(it); 71 } 72 } 73 74 void join_all() { 75 if (is_this_thread_in()) { 76 throw std::runtime_error("Trying joining itself in thread_group"); 77 } 78 for (auto &it : _threads) { 79 if (it.second->joinable()) { 80 it.second->join(); //等待线程主动退出 81 } 82 } 83 _threads.clear(); 84 } 85 86 size_t size() { 87 return _threads.size(); 88 } 89 90 private: 91 std::thread::id _thread_id; 92 std::unordered_map<std::thread::id, std::shared_ptr<std::thread>> _threads; 93 }; 94 95 } /* namespace toolkit */ 96 #endif /* THREADGROUP_H_ */
2.4 TaskExecutor.h
1 #ifndef ZLTOOLKIT_TASKEXECUTOR_H 2 #define ZLTOOLKIT_TASKEXECUTOR_H 3 4 #include <mutex> 5 #include <memory> 6 #include <functional> 7 #include "Util/List.h" 8 #include "Util/util.h" 9 10 namespace toolkit { 11 12 /** 13 * cpu负载计算器 14 * liu 按照cpu的 计算负载=运行时间*100/总时间;单位是us;乘以100,是因为按照百分比计算 15 */ 16 class ThreadLoadCounter { 17 public: 18 /** 19 * 构造函数 20 * @param max_size 统计样本数量 21 * @param max_usec 统计时间窗口,亦即最近{max_usec}的cpu负载率 22 */ 23 ThreadLoadCounter(uint64_t max_size, uint64_t max_usec); 24 ~ThreadLoadCounter() = default; 25 26 /** 27 * 线程进入休眠 28 */ 29 void startSleep(); 30 31 /** 32 * 休眠唤醒,结束休眠 33 */ 34 void sleepWakeUp(); 35 36 /** 37 * 返回当前线程cpu使用率,范围为 0 ~ 100 38 * @return 当前线程cpu使用率 39 */ 40 int load(); 41 42 private: 43 struct TimeRecord { 44 TimeRecord(uint64_t tm, bool slp) { 45 _time = tm; 46 _sleep = slp; 47 } 48 49 bool _sleep; 50 uint64_t _time; 51 }; 52 53 private: 54 bool _sleeping = true; 55 uint64_t _last_sleep_time; 56 uint64_t _last_wake_time; 57 uint64_t _max_size; 58 uint64_t _max_usec; 59 std::mutex _mtx; 60 /*liu 存放runtime-slp、sleeptime—slp的键值对,slp表示是否该时间是运行还是睡眠时间*/ 61 List<TimeRecord> _time_list; 62 }; 63 64 class TaskCancelable : public noncopyable { 65 public: 66 TaskCancelable() = default; 67 virtual ~TaskCancelable() = default; 68 virtual void cancel() = 0; 69 }; 70 71 template<class R, class... ArgTypes> 72 class TaskCancelableImp; 73 74 template<class R, class... ArgTypes> 75 class TaskCancelableImp<R(ArgTypes...)> : public TaskCancelable { 76 public: 77 using Ptr = std::shared_ptr<TaskCancelableImp>; 78 using func_type = std::function<R(ArgTypes...)>; 79 80 ~TaskCancelableImp() = default; 81 82 template<typename FUNC> 83 TaskCancelableImp(FUNC &&task) { 84 _strongTask = std::make_shared<func_type>(std::forward<FUNC>(task)); 85 _weakTask = _strongTask; 86 } 87 88 void cancel() override { 89 _strongTask = nullptr; 90 } 91 92 operator bool() { 93 return _strongTask && *_strongTask; 94 } 95 96 void operator=(std::nullptr_t) { 97 _strongTask = nullptr; 98 } 99 100 R operator()(ArgTypes ...args) const { 101 auto strongTask = _weakTask.lock(); 102 if (strongTask && *strongTask) { 103 return (*strongTask)(std::forward<ArgTypes>(args)...); 104 } 105 return defaultValue<R>(); 106 } 107 108 template<typename T> 109 static typename std::enable_if<std::is_void<T>::value, void>::type 110 defaultValue() {} 111 112 template<typename T> 113 static typename std::enable_if<std::is_pointer<T>::value, T>::type 114 defaultValue() { 115 return nullptr; 116 } 117 118 template<typename T> 119 static typename std::enable_if<std::is_integral<T>::value, T>::type 120 defaultValue() { 121 return 0; 122 } 123 124 protected: 125 std::weak_ptr<func_type> _weakTask; 126 std::shared_ptr<func_type> _strongTask; 127 }; 128 129 using TaskIn = std::function<void()>; 130 using Task = TaskCancelableImp<void()>; 131 132 class TaskExecutorInterface { 133 public: 134 TaskExecutorInterface() = default; 135 virtual ~TaskExecutorInterface() = default; 136 137 /** 138 * 异步执行任务 139 * @param task 任务 140 * @param may_sync 是否允许同步执行该任务 141 * @return 任务是否添加成功 142 */ 143 virtual Task::Ptr async(TaskIn task, bool may_sync = true) = 0; 144 145 /** 146 * 最高优先级方式异步执行任务 147 * @param task 任务 148 * @param may_sync 是否允许同步执行该任务 149 * @return 任务是否添加成功 150 */ 151 virtual Task::Ptr async_first(TaskIn task, bool may_sync = true); 152 153 /** 154 * 同步执行任务 155 * @param task 156 * @return 157 */ 158 void sync(const TaskIn &task); 159 160 /** 161 * 最高优先级方式同步执行任务 162 * @param task 163 * @return 164 */ 165 void sync_first(const TaskIn &task); 166 }; 167 168 /** 169 * 任务执行器 170 */ 171 class TaskExecutor : public ThreadLoadCounter, public TaskExecutorInterface { 172 public: 173 using Ptr = std::shared_ptr<TaskExecutor>; 174 175 /** 176 * 构造函数 177 * @param max_size cpu负载统计样本数 178 * @param max_usec cpu负载统计时间窗口大小 179 */ 180 TaskExecutor(uint64_t max_size = 32, uint64_t max_usec = 2 * 1000 * 1000); 181 ~TaskExecutor() = default; 182 }; 183 184 class TaskExecutorGetter { 185 public: 186 using Ptr = std::shared_ptr<TaskExecutorGetter>; 187 188 virtual ~TaskExecutorGetter() = default; 189 190 /** 191 * 获取任务执行器 192 * @return 任务执行器 193 */ 194 virtual TaskExecutor::Ptr getExecutor() = 0; 195 196 /** 197 * 获取执行器个数 198 */ 199 virtual size_t getExecutorSize() const = 0; 200 }; 201 202 class TaskExecutorGetterImp : public TaskExecutorGetter { 203 public: 204 TaskExecutorGetterImp() = default; 205 ~TaskExecutorGetterImp() = default; 206 207 /** 208 * 根据线程负载情况,获取最空闲的任务执行器 209 * @return 任务执行器 210 */ 211 TaskExecutor::Ptr getExecutor() override; 212 213 /** 214 * 获取所有线程的负载率 215 * @return 所有线程的负载率 216 */ 217 std::vector<int> getExecutorLoad(); 218 219 /** 220 * 获取所有线程任务执行延时,单位毫秒 221 * 通过此函数也可以大概知道线程负载情况 222 * @return 223 */ 224 void getExecutorDelay(const std::function<void(const std::vector<int> &)> &callback); 225 226 /** 227 * 遍历所有线程 228 */ 229 void for_each(const std::function<void(const TaskExecutor::Ptr &)> &cb); 230 231 /** 232 * 获取线程数 233 */ 234 size_t getExecutorSize() const override; 235 236 protected: 237 size_t addPoller(const std::string &name, size_t size, int priority, bool register_thread, bool enable_cpu_affinity = true); 238 239 protected: 240 size_t _thread_pos = 0; 241 std::vector<TaskExecutor::Ptr> _threads; 242 }; 243 244 }//toolkit 245 #endif //ZLTOOLKIT_TASKEXECUTOR_H
2.5 运行结果
1 E:\26_zlmediakit\11_ZLToolKit\__202311141609_202312281011_1_bak\__202311141609_bak\__202311141609\ZLToolKit\cmake-build-debug\bin\test_threadPool.exe 2 2024-01-03 16:26:03.594 D [test_threadPool.exe] [7824-stamp thread] util.cpp:367 operator () | Stamp thread started 3 2024-01-03 16:26:06.604 I [test_threadPool.exe] [7824-thread pool 0] test_threadPool.cpp:59 operator () | task 0 done! 4 2024-01-03 16:26:06.604 I [test_threadPool.exe] [7824-thread pool 1] test_threadPool.cpp:59 operator () | task 1 done! 5 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 9] test_threadPool.cpp:59 operator () | task 9 done! 6 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 10] test_threadPool.cpp:59 operator () | task 10 done! 7 8 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 2] test_threadPool.cpp:59 operator () | task 2 done! 9 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 11] test_threadPool.cpp:59 operator () | task 11 done! 10 11 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 8] test_threadPool.cpp:59 operator () | task 8 done! 12 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 5] test_threadPool.cpp:59 operator () | task 5 done! 13 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 6] test_threadPool.cpp:59 operator () | task 6 done! 14 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 4] test_threadPool.cpp:59 operator () | task 4 done! 15 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 3] test_threadPool.cpp:59 operator () | task 3 done! 16 2024-01-03 16:26:06.605 I [test_threadPool.exe] [7824-thread pool 7] test_threadPool.cpp:59 operator () | task 7 done! 17 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 12] test_threadPool.cpp:59 operator () | task 12 done! 18 19 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 21] test_threadPool.cpp:59 operator () | task 21 done! 20 21 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 19] test_threadPool.cpp:59 operator () | task 19 done! 22 23 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 17] test_threadPool.cpp:59 operator () | task 17 done! 24 25 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 13] test_threadPool.cpp:59 operator () | task 13 done! 26 27 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 20] test_threadPool.cpp:59 operator () | task 20 done! 28 29 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 15] test_threadPool.cpp:59 operator () | task 15 done! 30 31 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 22] test_threadPool.cpp:59 operator () | task 22 done! 32 33 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 14] test_threadPool.cpp:59 operator () | task 14 done! 34 35 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 16] test_threadPool.cpp:59 operator () | task 16 done! 36 37 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 23] test_threadPool.cpp:59 operator () | task 23 done! 38 39 2024-01-03 16:26:09.606 I [test_threadPool.exe] [7824-thread pool 18] test_threadPool.cpp:59 operator () | task 18 done! 40 41 2024-01-03 16:26:12.610 I [test_threadPool.exe] [7824-thread pool 31] test_threadPool.cpp:59 operator () | task 31 done! 42 43 2024-01-03 16:26:12.610 I [test_threadPool.exe] [7824-thread pool 26] test_threadPool.cpp:59 operator () | task 26 done! 44 45 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 30] test_threadPool.cpp:59 operator () | task 30 done! 46 47 2024-01-03 16:26:12.610 I [test_threadPool.exe] [7824-thread pool 29] test_threadPool.cpp:59 operator () | task 29 done! 48 49 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 32] test_threadPool.cpp:59 operator () | task 32 done! 50 51 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 28] test_threadPool.cpp:59 operator () | task 28 done! 52 53 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 33] test_threadPool.cpp:59 operator () | task 33 done! 54 55 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 24] test_threadPool.cpp:59 operator () | task 24 done! 56 57 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 25] test_threadPool.cpp:59 operator () | task 25 done! 58 59 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 34] test_threadPool.cpp:59 operator () | task 34 done! 60 61 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 27] test_threadPool.cpp:59 operator () | task 27 done! 62 63 2024-01-03 16:26:12.611 I [test_threadPool.exe] [7824-thread pool 35] test_threadPool.cpp:59 operator () | task 35 done! 64 65 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 44] test_threadPool.cpp:59 operator () | task 44 done! 66 67 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 43] test_threadPool.cpp:59 operator () | task 43 done! 68 69 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 36] test_threadPool.cpp:59 operator () | task 36 done! 70 71 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 38] test_threadPool.cpp:59 operator () | task 38 done! 72 73 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 39] test_threadPool.cpp:59 operator () | task 39 done! 74 75 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 45] test_threadPool.cpp:59 operator () | task 45 done! 76 77 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 42] test_threadPool.cpp:59 operator () | task 42 done! 78 79 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 46] test_threadPool.cpp:59 operator () | task 46 done! 80 81 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 40] test_threadPool.cpp:59 operator () | task 40 done! 82 83 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 37] test_threadPool.cpp:59 operator () | task 37 done! 84 85 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 41] test_threadPool.cpp:59 operator () | task 41 done! 86 87 2024-01-03 16:26:15.616 I [test_threadPool.exe] [7824-thread pool 47] test_threadPool.cpp:59 operator () | task 47 done! 88 89 2024-01-03 16:26:15.617 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:67 main | all task done, used millisecon 90 ds:12016 91 2024-01-03 16:26:15.619 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 0 92 2024-01-03 16:26:15.619 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 1 93 2024-01-03 16:26:15.619 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 2 94 2024-01-03 16:26:15.619 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 3 95 2024-01-03 16:26:15.619 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 4 96 2024-01-03 16:26:15.619 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 5 97 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 6 98 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 7 99 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 8 100 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 9 101 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 10 102 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 11 103 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 12 104 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 13 105 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 14 106 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 15 107 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 16 108 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 17 109 2024-01-03 16:26:15.620 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 18 110 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 19 111 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 20 112 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 21 113 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 22 114 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 23 115 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 24 116 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 25 117 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 26 118 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 27 119 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 28 120 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 29 121 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 30 122 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 31 123 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 32 124 2024-01-03 16:26:15.621 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 33 125 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 34 126 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 35 127 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 36 128 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 37 129 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 38 130 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 39 131 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 40 132 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 41 133 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 42 134 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 43 135 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 44 136 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 45 137 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 46 138 2024-01-03 16:26:15.622 I [test_threadPool.exe] [7824-9468] test_threadPool.cpp:71 main | 47 139 2024-01-03 16:26:15.691 I [test_threadPool.exe] [7824-9468] logger.cpp:86 ~Logger | 140 141 进程已结束,退出代码0
3.test_threadPoolBenchmark 注释
1 #include <csignal> 2 #include <atomic> 3 #include <iostream> 4 #include "Util/logger.h" 5 #include "Util/TimeTicker.h" 6 #include "Thread/ThreadPool.h" 7 8 using namespace std; 9 using namespace toolkit; 10 11 int main() { 12 signal(SIGINT,[](int ){ 13 exit(0); 14 }); 15 //初始化日志系统 16 Logger::Instance().add(std::make_shared<ConsoleChannel> ()); 17 18 atomic_llong count(0); 19 // liu 此处的 auto_run 设置的是false,不会直接开启线程执行 20 ThreadPool pool(1,ThreadPool::PRIORITY_HIGHEST, false); 21 22 Ticker ticker; 23 // liu 1000w个任务入队线程池耗时 24 for (int i = 0 ; i < 1000*10000;++i){ 25 pool.async([&](){ 26 if(++count >= 1000*10000){ 27 InfoL << "执行1000万任务总共耗时:" << ticker.elapsedTime() << "ms"; 28 } 29 }); 30 } 31 InfoL << "1000万任务入队耗时:" << ticker.elapsedTime() << "ms" << endl; 32 uint64_t lastCount = 0 ,nowCount = 1; 33 ticker.resetTime(); 34 //此处才开始启动线程 35 pool.start(); 36 while (true){ 37 sleep(1); 38 nowCount = count.load(); 39 InfoL << "每秒执行任务数:" << nowCount - lastCount; 40 if(nowCount - lastCount == 0){ 41 break; 42 } 43 lastCount = nowCount; 44 } 45 return 0; 46 } 47 /** 48 * 【运行结果对比】 49 * 相比与widows:ubuntu20.04下入队耗时时间长,但是每秒的任务执行效率高; 50 * 51 * ubuntu20.04 下的运行结果: 52 * /work/__202311141609_202312281011_bak/__202311141609_bak/__202311141609/ZLToolKit/cmake-build-debug/bin/test_threadPoolBenchmark 53 2024-01-03 15:36:05.254 D [test_threadPoolBenchmark] [13328-stamp thread] util.cpp:367 operator() | Stamp thread started 54 2024-01-03 15:36:14.965 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:40 main | 1000万任务入队耗时:9709ms 55 2024-01-03 15:36:15.966 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1122279 56 2024-01-03 15:36:16.966 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1141750 57 2024-01-03 15:36:17.966 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1146485 58 2024-01-03 15:36:18.966 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1134105 59 2024-01-03 15:36:19.967 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1109435 60 2024-01-03 15:36:20.967 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1127861 61 2024-01-03 15:36:21.967 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1137880 62 2024-01-03 15:36:22.968 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:1131760 63 2024-01-03 15:36:23.842 I [test_threadPoolBenchmark] [13328-thread pool 0] test_threadPoolBenchmark.cpp:36 operator() | 执行1000万任务总共耗时:8878ms 64 2024-01-03 15:36:23.968 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:948445 65 2024-01-03 15:36:24.969 I [test_threadPoolBenchmark] [13328-test_threadPool] test_threadPoolBenchmark.cpp:48 main | 每秒执行任务数:0 66 2024-01-03 15:36:24.969 I [test_threadPoolBenchmark] [13328-test_threadPool] logger.cpp:86 ~Logger | 67 68 进程已结束,退出代码0 69 ============================ 70 windows下的运行结果: 71 2024-01-03 15:37:43.140 D [test_threadPoolBenchmark.exe] [18316-stamp thread] util.cpp:366 operator () | Stamp thread started 72 2024-01-03 15:37:56.332 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:39 main | 1000万任务入队耗时:13183ms 73 2024-01-03 15:37:57.336 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:574157 74 2024-01-03 15:37:58.340 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:550270 75 2024-01-03 15:37:59.344 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:578763 76 2024-01-03 15:38:00.348 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:574638 77 2024-01-03 15:38:01.354 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:581882 78 2024-01-03 15:38:02.357 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:580594 79 2024-01-03 15:38:03.361 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:581774 80 2024-01-03 15:38:04.365 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:584657 81 2024-01-03 15:38:05.370 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:586089 82 2024-01-03 15:38:06.374 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:585166 83 2024-01-03 15:38:07.379 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:584371 84 2024-01-03 15:38:08.384 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:582507 85 2024-01-03 15:38:09.390 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:587002 86 2024-01-03 15:38:10.391 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:588688 87 2024-01-03 15:38:11.393 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:577069 88 2024-01-03 15:38:12.396 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:579160 89 2024-01-03 15:38:13.399 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:576091 90 2024-01-03 15:38:13.650 I [test_threadPoolBenchmark.exe] [18316-thread pool 0] test_threadPoolBenchmark.cpp:35 operator () | 执行1000万任务总共耗时:17315ms 91 2024-01-03 15:38:14.403 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:147122 92 2024-01-03 15:38:15.406 I [test_threadPoolBenchmark.exe] [18316-2144] test_threadPoolBenchmark.cpp:47 main | 每秒执行任务数:0 93 2024-01-03 15:38:15.409 I [test_threadPoolBenchmark.exe] [18316-2144] logger.cpp:86 ~Logger | 94 95 E:\26_zlmediakit\11_ZLToolKit\__202311141609-vs\__202311141609\ZLToolKit\bin\Debug\test_threadPoolBenchmark.exe (进程 18316)已退出,代码为 0。 96 按任意键关闭此窗口. . . 97 98 99 100 */
4.参考onceToken解析
https://github.com/ZLMediaKit/ZLMediaKit/wiki/%E4%BB%A3%E7%A0%81%E7%AF%87%E4%B9%8BonceToken
这里是作者的解析,原地址如上