| 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 |  | 
|---|