1 #include "LibcBenchmark.h" 2 #include "LibcMemoryBenchmark.h" 3 #include "MemorySizeDistributions.h" 4 #include "benchmark/benchmark.h" 5 #include <cstdint> 6 #include <random> 7 #include <vector> 8 9 namespace __llvm_libc { 10 11 extern void *memcpy(void *__restrict, const void *__restrict, size_t); 12 extern void *memset(void *, int, size_t); 13 extern void bzero(void *, size_t); 14 extern int memcmp(const void *, const void *, size_t); 15 16 } // namespace __llvm_libc 17 18 using llvm::Align; 19 using llvm::ArrayRef; 20 using llvm::libc_benchmarks::ComparisonHarness; 21 using llvm::libc_benchmarks::CopyHarness; 22 using llvm::libc_benchmarks::MemorySizeDistribution; 23 using llvm::libc_benchmarks::OffsetDistribution; 24 using llvm::libc_benchmarks::SetHarness; 25 26 static constexpr Align kBenchmarkAlignment = Align::Constant<1>(); 27 28 template <typename Harness> struct Randomized : public Harness { 29 Randomized(benchmark::State &State) 30 : State(State), Distribution(Harness::getDistributions()[State.range(0)]), 31 Probabilities(Distribution.Probabilities), 32 SizeSampler(Probabilities.begin(), Probabilities.end()), 33 OffsetSampler(Harness::BufferSize, Probabilities.size() - 1, 34 kBenchmarkAlignment) { 35 for (auto &P : Harness::Parameters) { 36 P.OffsetBytes = OffsetSampler(Gen); 37 P.SizeBytes = SizeSampler(Gen); 38 Harness::checkValid(P); 39 } 40 } 41 42 ~Randomized() { 43 const size_t AvgBytesPerIteration = 44 Harness::getBatchBytes() / Harness::BatchSize; 45 const size_t TotalBytes = State.iterations() * AvgBytesPerIteration; 46 State.SetBytesProcessed(TotalBytes); 47 State.SetLabel(Distribution.Name.str()); 48 State.counters["bytes_per_cycle"] = benchmark::Counter( 49 TotalBytes / benchmark::CPUInfo::Get().cycles_per_second, 50 benchmark::Counter::kIsRate); 51 } 52 53 template <typename Function> inline void runBatch(Function foo) { 54 for (const auto &P : Harness::Parameters) 55 benchmark::DoNotOptimize(Harness::Call(P, foo)); 56 } 57 58 private: 59 benchmark::State &State; 60 Harness UP; 61 MemorySizeDistribution Distribution; 62 ArrayRef<double> Probabilities; 63 std::discrete_distribution<unsigned> SizeSampler; 64 OffsetDistribution OffsetSampler; 65 std::mt19937_64 Gen; 66 }; 67 68 template <typename Harness> static int64_t getMaxIndex() { 69 return Harness::getDistributions().size() - 1; 70 } 71 72 void BM_Memcpy(benchmark::State &State) { 73 Randomized<CopyHarness> Harness(State); 74 while (State.KeepRunningBatch(Harness.BatchSize)) 75 Harness.runBatch(__llvm_libc::memcpy); 76 } 77 BENCHMARK(BM_Memcpy)->DenseRange(0, getMaxIndex<CopyHarness>()); 78 79 void BM_Memcmp(benchmark::State &State) { 80 Randomized<ComparisonHarness> Harness(State); 81 while (State.KeepRunningBatch(Harness.BatchSize)) 82 Harness.runBatch(__llvm_libc::memcmp); 83 } 84 BENCHMARK(BM_Memcmp)->DenseRange(0, getMaxIndex<ComparisonHarness>()); 85 86 void BM_Memset(benchmark::State &State) { 87 Randomized<SetHarness> Harness(State); 88 while (State.KeepRunningBatch(Harness.BatchSize)) 89 Harness.runBatch(__llvm_libc::memset); 90 } 91 BENCHMARK(BM_Memset)->DenseRange(0, getMaxIndex<SetHarness>()); 92 93 void BM_Bzero(benchmark::State &State) { 94 Randomized<SetHarness> Harness(State); 95 while (State.KeepRunningBatch(Harness.BatchSize)) 96 Harness.runBatch(__llvm_libc::bzero); 97 } 98 BENCHMARK(BM_Bzero)->DenseRange(0, getMaxIndex<SetHarness>()); 99