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_handle117      * 【参考:重要文章】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/547970094122      * @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, &params) == 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

这里是作者的解析,原地址如上

 

posted @ 2024-01-03 16:04  OzTaking  阅读(3)  评论(0编辑  收藏  举报