|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 | #include "sanitizer_common/sanitizer_stackdepot.h"
|
13 | 13 |
|
| 14 | +#include <atomic> |
| 15 | +#include <numeric> |
14 | 16 | #include <regex>
|
| 17 | +#include <sstream> |
| 18 | +#include <string> |
| 19 | +#include <thread> |
15 | 20 |
|
16 | 21 | #include "gtest/gtest.h"
|
17 | 22 | #include "sanitizer_common/sanitizer_internal_defs.h"
|
@@ -106,4 +111,81 @@ TEST(SanitizerCommon, StackDepotPrintNoLock) {
|
106 | 111 | }
|
107 | 112 | }
|
108 | 113 |
|
| 114 | +static struct SanitizerCommonBenchmarkparams { |
| 115 | + int UniqueStacksPerThread; |
| 116 | + int RepeatPerThread; |
| 117 | + int Threads; |
| 118 | + bool UniqueThreads; |
| 119 | + bool UseCount; |
| 120 | +} Params[] = { |
| 121 | + // All traces are unique, very unusual. |
| 122 | + {10000000, 1, 1}, |
| 123 | + {8000000, 1, 4}, |
| 124 | + {8000000, 1, 16}, |
| 125 | + // Probably most realistic sets. |
| 126 | + {3000000, 10, 1}, |
| 127 | + {3000000, 10, 4}, |
| 128 | + {3000000, 10, 16}, |
| 129 | + // Update use count as msan/dfsan. |
| 130 | + {3000000, 10, 16, false, true}, |
| 131 | + // As above, but traces are unique inside of thread. |
| 132 | + {4000000, 1, 4, true}, |
| 133 | + {2000000, 1, 16, true}, |
| 134 | + {2000000, 10, 4, true}, |
| 135 | + {500000, 10, 16, true}, |
| 136 | + {3000000, 10, 16, true, true}, |
| 137 | +}; |
| 138 | + |
| 139 | +std::string PrintSanitizerCommonBenchmarkparams( |
| 140 | + const testing::TestParamInfo<SanitizerCommonBenchmarkparams>& info) { |
| 141 | + std::stringstream name; |
| 142 | + name << info.param.UniqueStacksPerThread << "_" << info.param.RepeatPerThread |
| 143 | + << "_" << info.param.Threads << (info.param.UseCount ? "_UseCount" : "") |
| 144 | + << (info.param.UniqueThreads ? "_UniqueThreads" : ""); |
| 145 | + return name.str(); |
| 146 | +} |
| 147 | + |
| 148 | +class SanitizerCommonBenchmark |
| 149 | + : public testing::TestWithParam<SanitizerCommonBenchmarkparams> { |
| 150 | + protected: |
| 151 | + void Run() { |
| 152 | + auto Param = GetParam(); |
| 153 | + std::atomic<unsigned int> here = {}; |
| 154 | + |
| 155 | + auto thread = [&](int idx) { |
| 156 | + here++; |
| 157 | + while (here < Param.UniqueThreads) std::this_thread::yield(); |
| 158 | + |
| 159 | + std::vector<uptr> frames(64); |
| 160 | + for (int r = 0; r < Param.RepeatPerThread; ++r) { |
| 161 | + std::iota(frames.begin(), frames.end(), idx + 1); |
| 162 | + for (int i = 0; i < Param.UniqueStacksPerThread; ++i) { |
| 163 | + StackTrace s(frames.data(), frames.size()); |
| 164 | + auto h = StackDepotPut_WithHandle(s); |
| 165 | + if (Param.UseCount) |
| 166 | + h.inc_use_count_unsafe(); |
| 167 | + std::next_permutation(frames.begin(), frames.end()); |
| 168 | + }; |
| 169 | + } |
| 170 | + }; |
| 171 | + |
| 172 | + std::vector<std::thread> threads; |
| 173 | + for (int i = 0; i < Param.Threads; ++i) |
| 174 | + threads.emplace_back(thread, Param.UniqueThreads * i); |
| 175 | + for (auto& t : threads) t.join(); |
| 176 | + } |
| 177 | +}; |
| 178 | + |
| 179 | +// Test which can be used as a simple benchmark. It's disabled to avoid slowing |
| 180 | +// down check-sanitizer. |
| 181 | +// Usage: Sanitizer-<ARCH>-Test --gtest_also_run_disabled_tests \ |
| 182 | +// '--gtest_filter=*Benchmark*' |
| 183 | +TEST_P(SanitizerCommonBenchmark, DISABLED_BenchmarkInsertUniqueThreaded) { |
| 184 | + EXPECT_EXIT((Run(), exit(0)), ::testing::ExitedWithCode(0), ""); |
| 185 | +} |
| 186 | + |
| 187 | +INSTANTIATE_TEST_SUITE_P(SanitizerCommonBenchmarkSuite, |
| 188 | + SanitizerCommonBenchmark, testing::ValuesIn(Params), |
| 189 | + PrintSanitizerCommonBenchmarkparams); |
| 190 | + |
109 | 191 | } // namespace __sanitizer
|
0 commit comments