1 | #include <iostream> |
2 | #include <iomanip> |
3 | |
4 | #include <IO/ReadHelpers.h> |
5 | |
6 | #include <Common/Stopwatch.h> |
7 | #include <Common/Exception.h> |
8 | #include <Common/ThreadPool.h> |
9 | |
10 | |
11 | int value = 0; |
12 | |
13 | static void f() { ++value; } |
14 | static void * g(void *) { f(); return {}; } |
15 | |
16 | |
17 | namespace DB |
18 | { |
19 | namespace ErrorCodes |
20 | { |
21 | extern const int PTHREAD_ERROR; |
22 | } |
23 | } |
24 | |
25 | |
26 | template <typename F> |
27 | void test(size_t n, const char * name, F && kernel) |
28 | { |
29 | value = 0; |
30 | |
31 | Stopwatch watch; |
32 | Stopwatch watch_one; |
33 | double max_seconds = 0; |
34 | |
35 | std::cerr << name << ":\n" ; |
36 | |
37 | for (size_t i = 0; i < n; ++i) |
38 | { |
39 | watch_one.restart(); |
40 | |
41 | kernel(); |
42 | |
43 | watch_one.stop(); |
44 | if (watch_one.elapsedSeconds() > max_seconds) |
45 | max_seconds = watch_one.elapsedSeconds(); |
46 | } |
47 | |
48 | watch.stop(); |
49 | |
50 | std::cerr |
51 | << std::fixed << std::setprecision(2) |
52 | << n << " ops in " |
53 | << watch.elapsedSeconds() << " sec., " |
54 | << n / watch.elapsedSeconds() << " ops/sec., " |
55 | << "avg latency: " << watch.elapsedSeconds() / n * 1000000 << " μs, " |
56 | << "max latency: " << max_seconds * 1000000 << " μs " |
57 | << "(res = " << value << ")" |
58 | << std::endl; |
59 | } |
60 | |
61 | |
62 | int main(int argc, char ** argv) |
63 | { |
64 | size_t n = argc == 2 ? DB::parse<UInt64>(argv[1]) : 100000; |
65 | |
66 | test(n, "Create and destroy ThreadPool each iteration" , [] |
67 | { |
68 | ThreadPool tp(1); |
69 | tp.scheduleOrThrowOnError(f); |
70 | tp.wait(); |
71 | }); |
72 | |
73 | test(n, "pthread_create, pthread_join each iteration" , [] |
74 | { |
75 | pthread_t thread; |
76 | if (pthread_create(&thread, nullptr, g, nullptr)) |
77 | DB::throwFromErrno("Cannot create thread." , DB::ErrorCodes::PTHREAD_ERROR); |
78 | if (pthread_join(thread, nullptr)) |
79 | DB::throwFromErrno("Cannot join thread." , DB::ErrorCodes::PTHREAD_ERROR); |
80 | }); |
81 | |
82 | test(n, "Create and destroy std::thread each iteration" , [] |
83 | { |
84 | std::thread thread(f); |
85 | thread.join(); |
86 | }); |
87 | |
88 | { |
89 | ThreadPool tp(1); |
90 | |
91 | test(n, "Schedule job for Threadpool each iteration" , [&tp] |
92 | { |
93 | tp.scheduleOrThrowOnError(f); |
94 | tp.wait(); |
95 | }); |
96 | } |
97 | |
98 | { |
99 | ThreadPool tp(128); |
100 | |
101 | test(n, "Schedule job for Threadpool with 128 threads each iteration" , [&tp] |
102 | { |
103 | tp.scheduleOrThrowOnError(f); |
104 | tp.wait(); |
105 | }); |
106 | } |
107 | |
108 | return 0; |
109 | } |
110 | |