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