| 1 | #include <Common/ThreadPool.h> |
| 2 | #include <IO/ReadBufferFromFile.h> |
| 3 | #include <IO/WriteBufferFromFile.h> |
| 4 | #include <IO/copyData.h> |
| 5 | #include <Common/TaskStatsInfoGetter.h> |
| 6 | #include <Poco/File.h> |
| 7 | #include <Common/Stopwatch.h> |
| 8 | #include <IO/WriteBufferFromString.h> |
| 9 | #include <linux/taskstats.h> |
| 10 | #include <sys/time.h> |
| 11 | #include <sys/resource.h> |
| 12 | #include <pthread.h> |
| 13 | |
| 14 | |
| 15 | std::mutex mutex; |
| 16 | |
| 17 | |
| 18 | static std::ostream & operator << (std::ostream & stream, const ::taskstats & stat) |
| 19 | { |
| 20 | #define PRINT(field) (stream << #field << " " << stat.field) |
| 21 | |
| 22 | PRINT(ac_pid) << ", " ; |
| 23 | |
| 24 | PRINT(read_bytes) << ", " ; |
| 25 | PRINT(write_bytes) << ", " ; |
| 26 | |
| 27 | PRINT(read_char) << ", " ; |
| 28 | PRINT(write_char) << ", " ; |
| 29 | |
| 30 | PRINT(swapin_delay_total) << ", " ; |
| 31 | PRINT(blkio_delay_total) << ", " ; |
| 32 | PRINT(cpu_delay_total) << ", " ; |
| 33 | |
| 34 | PRINT(ac_pid) << ", " ; |
| 35 | |
| 36 | PRINT(ac_utime) << ", " ; |
| 37 | PRINT(ac_stime) << ", " ; |
| 38 | |
| 39 | #undef PRINT |
| 40 | |
| 41 | return stream; |
| 42 | } |
| 43 | |
| 44 | using namespace DB; |
| 45 | |
| 46 | |
| 47 | static void do_io(size_t id) |
| 48 | { |
| 49 | ::taskstats stat; |
| 50 | int tid = TaskStatsInfoGetter::getCurrentTID(); |
| 51 | TaskStatsInfoGetter get_info; |
| 52 | |
| 53 | get_info.getStat(stat, tid); |
| 54 | { |
| 55 | std::lock_guard lock(mutex); |
| 56 | std::cerr << "#" << id << ", tid " << tid << ", intitial\n" << stat << "\n" ; |
| 57 | } |
| 58 | |
| 59 | size_t copy_size = 1048576 * (1 + id); |
| 60 | std::string path_dst = "test_out_" + std::to_string(id); |
| 61 | |
| 62 | { |
| 63 | ReadBufferFromFile rb("/dev/urandom" ); |
| 64 | WriteBufferFromFile wb(path_dst, DBMS_DEFAULT_BUFFER_SIZE, O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666, nullptr, 4096); |
| 65 | copyData(rb, wb, copy_size); |
| 66 | wb.close(); |
| 67 | } |
| 68 | |
| 69 | get_info.getStat(stat, tid); |
| 70 | { |
| 71 | std::lock_guard lock(mutex); |
| 72 | std::cerr << "#" << id << ", tid " << tid << ", step1\n" << stat << "\n" ; |
| 73 | } |
| 74 | |
| 75 | { |
| 76 | ReadBufferFromFile rb(path_dst); |
| 77 | WriteBufferFromOwnString wb; |
| 78 | copyData(rb, wb, copy_size); |
| 79 | } |
| 80 | |
| 81 | get_info.getStat(stat, tid); |
| 82 | { |
| 83 | std::lock_guard lock(mutex); |
| 84 | std::cerr << "#" << id << ", tid " << tid << ", step2\n" << stat << "\n" ; |
| 85 | } |
| 86 | |
| 87 | { |
| 88 | ReadBufferFromFile rb(path_dst); |
| 89 | WriteBufferFromOwnString wb; |
| 90 | copyData(rb, wb, copy_size); |
| 91 | } |
| 92 | |
| 93 | get_info.getStat(stat, tid); |
| 94 | { |
| 95 | std::lock_guard lock(mutex); |
| 96 | std::cerr << "#" << id << ", tid " << tid << ", step3\n" << stat << "\n" ; |
| 97 | } |
| 98 | |
| 99 | Poco::File(path_dst).remove(false); |
| 100 | } |
| 101 | |
| 102 | static void test_perf() |
| 103 | { |
| 104 | |
| 105 | ::taskstats stat; |
| 106 | int tid = TaskStatsInfoGetter::getCurrentTID(); |
| 107 | TaskStatsInfoGetter get_info; |
| 108 | |
| 109 | rusage rusage; |
| 110 | |
| 111 | constexpr size_t num_samples = 1000000; |
| 112 | { |
| 113 | Stopwatch watch; |
| 114 | for (size_t i = 0; i < num_samples; ++i) |
| 115 | getrusage(RUSAGE_THREAD, &rusage); |
| 116 | |
| 117 | auto ms = watch.elapsedMilliseconds(); |
| 118 | if (ms > 0) |
| 119 | std::cerr << "RUsage: " << double(ms) / num_samples << " ms per call, " << 1000 * num_samples / ms << " calls per second\n" ; |
| 120 | } |
| 121 | |
| 122 | { |
| 123 | Stopwatch watch; |
| 124 | for (size_t i = 0; i < num_samples; ++i) |
| 125 | get_info.getStat(stat, tid); |
| 126 | |
| 127 | auto ms = watch.elapsedMilliseconds(); |
| 128 | if (ms > 0) |
| 129 | std::cerr << "Netlink: " << double(ms) / num_samples << " ms per call, " << 1000 * num_samples / ms << " calls per second\n" ; |
| 130 | } |
| 131 | |
| 132 | std::cerr << stat << "\n" ; |
| 133 | } |
| 134 | |
| 135 | int main() |
| 136 | try |
| 137 | { |
| 138 | std::cerr << "pid " << getpid() << "\n" ; |
| 139 | |
| 140 | size_t num_threads = 2; |
| 141 | ThreadPool pool(num_threads); |
| 142 | for (size_t i = 0; i < num_threads; ++i) |
| 143 | pool.scheduleOrThrowOnError([i]() { do_io(i); }); |
| 144 | pool.wait(); |
| 145 | |
| 146 | test_perf(); |
| 147 | return 0; |
| 148 | } |
| 149 | catch (...) |
| 150 | { |
| 151 | std::cerr << getCurrentExceptionMessage(true); |
| 152 | return -1; |
| 153 | } |
| 154 | |
| 155 | |