1 #include "LibcBenchmark.h"
2 #include "LibcMemoryBenchmark.h"
3 #include "MemorySizeDistributions.h"
4 #include "benchmark/benchmark.h"
5 #include "llvm/ADT/ArrayRef.h"
6 #include "llvm/ADT/Twine.h"
7 #include <chrono>
8 #include <cstdint>
9 #include <random>
10 #include <vector>
11
12 using llvm::Align;
13 using llvm::ArrayRef;
14 using llvm::Twine;
15 using llvm::libc_benchmarks::BzeroConfiguration;
16 using llvm::libc_benchmarks::ComparisonSetup;
17 using llvm::libc_benchmarks::CopySetup;
18 using llvm::libc_benchmarks::MemcmpConfiguration;
19 using llvm::libc_benchmarks::MemcpyConfiguration;
20 using llvm::libc_benchmarks::MemorySizeDistribution;
21 using llvm::libc_benchmarks::MemsetConfiguration;
22 using llvm::libc_benchmarks::OffsetDistribution;
23 using llvm::libc_benchmarks::SetSetup;
24
25 // Alignment to use for when accessing the buffers.
26 static constexpr Align kBenchmarkAlignment = Align::Constant<1>();
27
getGenerator()28 static std::mt19937_64 &getGenerator() {
29 static std::mt19937_64 Generator(
30 std::chrono::system_clock::now().time_since_epoch().count());
31 return Generator;
32 }
33
34 template <typename SetupType, typename ConfigurationType> struct Runner {
RunnerRunner35 Runner(benchmark::State &S, llvm::ArrayRef<ConfigurationType> Configurations)
36 : State(S), Distribution(SetupType::getDistributions()[State.range(0)]),
37 Probabilities(Distribution.Probabilities),
38 SizeSampler(Probabilities.begin(), Probabilities.end()),
39 OffsetSampler(Setup.BufferSize, Probabilities.size() - 1,
40 kBenchmarkAlignment),
41 Configuration(Configurations[State.range(1)]) {
42 for (auto &P : Setup.Parameters) {
43 P.OffsetBytes = OffsetSampler(getGenerator());
44 P.SizeBytes = SizeSampler(getGenerator());
45 Setup.checkValid(P);
46 }
47 }
48
~RunnerRunner49 ~Runner() {
50 const size_t AvgBytesPerIteration = Setup.getBatchBytes() / Setup.BatchSize;
51 const size_t TotalBytes = State.iterations() * AvgBytesPerIteration;
52 State.SetBytesProcessed(TotalBytes);
53 State.SetItemsProcessed(State.iterations());
54 State.SetLabel((Twine(Configuration.Name) + "," + Distribution.Name).str());
55 State.counters["bytes_per_cycle"] = benchmark::Counter(
56 TotalBytes / benchmark::CPUInfo::Get().cycles_per_second,
57 benchmark::Counter::kIsRate);
58 }
59
runBatchRunner60 inline void runBatch() {
61 for (const auto &P : Setup.Parameters)
62 benchmark::DoNotOptimize(Setup.Call(P, Configuration.Function));
63 }
64
getBatchSizeRunner65 size_t getBatchSize() const { return Setup.BatchSize; }
66
67 private:
68 SetupType Setup;
69 benchmark::State &State;
70 MemorySizeDistribution Distribution;
71 ArrayRef<double> Probabilities;
72 std::discrete_distribution<unsigned> SizeSampler;
73 OffsetDistribution OffsetSampler;
74 ConfigurationType Configuration;
75 };
76
77 #define BENCHMARK_MEMORY_FUNCTION(BM_NAME, SETUP, CONFIGURATION_TYPE, \
78 CONFIGURATION_ARRAY_REF) \
79 void BM_NAME(benchmark::State &State) { \
80 Runner<SETUP, CONFIGURATION_TYPE> Setup(State, CONFIGURATION_ARRAY_REF); \
81 const size_t BatchSize = Setup.getBatchSize(); \
82 while (State.KeepRunningBatch(BatchSize)) \
83 Setup.runBatch(); \
84 } \
85 BENCHMARK(BM_NAME)->Apply([](benchmark::internal::Benchmark *benchmark) { \
86 const int64_t DistributionSize = SETUP::getDistributions().size(); \
87 const int64_t ConfigurationSize = CONFIGURATION_ARRAY_REF.size(); \
88 for (int64_t DistIndex = 0; DistIndex < DistributionSize; ++DistIndex) \
89 for (int64_t ConfIndex = 0; ConfIndex < ConfigurationSize; ++ConfIndex) \
90 benchmark->Args({DistIndex, ConfIndex}); \
91 })
92
93 extern llvm::ArrayRef<MemcpyConfiguration> getMemcpyConfigurations();
94 BENCHMARK_MEMORY_FUNCTION(BM_Memcpy, CopySetup, MemcpyConfiguration,
95 getMemcpyConfigurations());
96
97 extern llvm::ArrayRef<MemcmpConfiguration> getMemcmpConfigurations();
98 BENCHMARK_MEMORY_FUNCTION(BM_Memcmp, ComparisonSetup, MemcmpConfiguration,
99 getMemcmpConfigurations());
100
101 extern llvm::ArrayRef<MemcmpConfiguration> getBcmpConfigurations();
102 BENCHMARK_MEMORY_FUNCTION(BM_Bcmp, ComparisonSetup, MemcmpConfiguration,
103 getBcmpConfigurations());
104
105 extern llvm::ArrayRef<MemsetConfiguration> getMemsetConfigurations();
106 BENCHMARK_MEMORY_FUNCTION(BM_Memset, SetSetup, MemsetConfiguration,
107 getMemsetConfigurations());
108
109 extern llvm::ArrayRef<BzeroConfiguration> getBzeroConfigurations();
110 BENCHMARK_MEMORY_FUNCTION(BM_Bzero, SetSetup, BzeroConfiguration,
111 getBzeroConfigurations());
112