xref: /aosp_15_r20/external/google-benchmark/bindings/python/google_benchmark/benchmark.cc (revision dbb99499c3810fa1611fa2242a2fc446be01a57c)
1*dbb99499SAndroid Build Coastguard Worker // Benchmark for Python.
2*dbb99499SAndroid Build Coastguard Worker 
3*dbb99499SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
4*dbb99499SAndroid Build Coastguard Worker 
5*dbb99499SAndroid Build Coastguard Worker #include "nanobind/nanobind.h"
6*dbb99499SAndroid Build Coastguard Worker #include "nanobind/operators.h"
7*dbb99499SAndroid Build Coastguard Worker #include "nanobind/stl/bind_map.h"
8*dbb99499SAndroid Build Coastguard Worker #include "nanobind/stl/string.h"
9*dbb99499SAndroid Build Coastguard Worker #include "nanobind/stl/vector.h"
10*dbb99499SAndroid Build Coastguard Worker 
11*dbb99499SAndroid Build Coastguard Worker NB_MAKE_OPAQUE(benchmark::UserCounters);
12*dbb99499SAndroid Build Coastguard Worker 
13*dbb99499SAndroid Build Coastguard Worker namespace {
14*dbb99499SAndroid Build Coastguard Worker namespace nb = nanobind;
15*dbb99499SAndroid Build Coastguard Worker 
Initialize(const std::vector<std::string> & argv)16*dbb99499SAndroid Build Coastguard Worker std::vector<std::string> Initialize(const std::vector<std::string>& argv) {
17*dbb99499SAndroid Build Coastguard Worker   // The `argv` pointers here become invalid when this function returns, but
18*dbb99499SAndroid Build Coastguard Worker   // benchmark holds the pointer to `argv[0]`. We create a static copy of it
19*dbb99499SAndroid Build Coastguard Worker   // so it persists, and replace the pointer below.
20*dbb99499SAndroid Build Coastguard Worker   static std::string executable_name(argv[0]);
21*dbb99499SAndroid Build Coastguard Worker   std::vector<char*> ptrs;
22*dbb99499SAndroid Build Coastguard Worker   ptrs.reserve(argv.size());
23*dbb99499SAndroid Build Coastguard Worker   for (auto& arg : argv) {
24*dbb99499SAndroid Build Coastguard Worker     ptrs.push_back(const_cast<char*>(arg.c_str()));
25*dbb99499SAndroid Build Coastguard Worker   }
26*dbb99499SAndroid Build Coastguard Worker   ptrs[0] = const_cast<char*>(executable_name.c_str());
27*dbb99499SAndroid Build Coastguard Worker   int argc = static_cast<int>(argv.size());
28*dbb99499SAndroid Build Coastguard Worker   benchmark::Initialize(&argc, ptrs.data());
29*dbb99499SAndroid Build Coastguard Worker   std::vector<std::string> remaining_argv;
30*dbb99499SAndroid Build Coastguard Worker   remaining_argv.reserve(argc);
31*dbb99499SAndroid Build Coastguard Worker   for (int i = 0; i < argc; ++i) {
32*dbb99499SAndroid Build Coastguard Worker     remaining_argv.emplace_back(ptrs[i]);
33*dbb99499SAndroid Build Coastguard Worker   }
34*dbb99499SAndroid Build Coastguard Worker   return remaining_argv;
35*dbb99499SAndroid Build Coastguard Worker }
36*dbb99499SAndroid Build Coastguard Worker 
RegisterBenchmark(const std::string & name,nb::callable f)37*dbb99499SAndroid Build Coastguard Worker benchmark::internal::Benchmark* RegisterBenchmark(const std::string& name,
38*dbb99499SAndroid Build Coastguard Worker                                                   nb::callable f) {
39*dbb99499SAndroid Build Coastguard Worker   return benchmark::RegisterBenchmark(
40*dbb99499SAndroid Build Coastguard Worker       name, [f](benchmark::State& state) { f(&state); });
41*dbb99499SAndroid Build Coastguard Worker }
42*dbb99499SAndroid Build Coastguard Worker 
NB_MODULE(_benchmark,m)43*dbb99499SAndroid Build Coastguard Worker NB_MODULE(_benchmark, m) {
44*dbb99499SAndroid Build Coastguard Worker 
45*dbb99499SAndroid Build Coastguard Worker   using benchmark::TimeUnit;
46*dbb99499SAndroid Build Coastguard Worker   nb::enum_<TimeUnit>(m, "TimeUnit")
47*dbb99499SAndroid Build Coastguard Worker       .value("kNanosecond", TimeUnit::kNanosecond)
48*dbb99499SAndroid Build Coastguard Worker       .value("kMicrosecond", TimeUnit::kMicrosecond)
49*dbb99499SAndroid Build Coastguard Worker       .value("kMillisecond", TimeUnit::kMillisecond)
50*dbb99499SAndroid Build Coastguard Worker       .value("kSecond", TimeUnit::kSecond)
51*dbb99499SAndroid Build Coastguard Worker       .export_values();
52*dbb99499SAndroid Build Coastguard Worker 
53*dbb99499SAndroid Build Coastguard Worker   using benchmark::BigO;
54*dbb99499SAndroid Build Coastguard Worker   nb::enum_<BigO>(m, "BigO")
55*dbb99499SAndroid Build Coastguard Worker       .value("oNone", BigO::oNone)
56*dbb99499SAndroid Build Coastguard Worker       .value("o1", BigO::o1)
57*dbb99499SAndroid Build Coastguard Worker       .value("oN", BigO::oN)
58*dbb99499SAndroid Build Coastguard Worker       .value("oNSquared", BigO::oNSquared)
59*dbb99499SAndroid Build Coastguard Worker       .value("oNCubed", BigO::oNCubed)
60*dbb99499SAndroid Build Coastguard Worker       .value("oLogN", BigO::oLogN)
61*dbb99499SAndroid Build Coastguard Worker       .value("oNLogN", BigO::oNLogN)
62*dbb99499SAndroid Build Coastguard Worker       .value("oAuto", BigO::oAuto)
63*dbb99499SAndroid Build Coastguard Worker       .value("oLambda", BigO::oLambda)
64*dbb99499SAndroid Build Coastguard Worker       .export_values();
65*dbb99499SAndroid Build Coastguard Worker 
66*dbb99499SAndroid Build Coastguard Worker   using benchmark::internal::Benchmark;
67*dbb99499SAndroid Build Coastguard Worker   nb::class_<Benchmark>(m, "Benchmark")
68*dbb99499SAndroid Build Coastguard Worker       // For methods returning a pointer to the current object, reference
69*dbb99499SAndroid Build Coastguard Worker       // return policy is used to ask nanobind not to take ownership of the
70*dbb99499SAndroid Build Coastguard Worker       // returned object and avoid calling delete on it.
71*dbb99499SAndroid Build Coastguard Worker       // https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
72*dbb99499SAndroid Build Coastguard Worker       //
73*dbb99499SAndroid Build Coastguard Worker       // For methods taking a const std::vector<...>&, a copy is created
74*dbb99499SAndroid Build Coastguard Worker       // because a it is bound to a Python list.
75*dbb99499SAndroid Build Coastguard Worker       // https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html
76*dbb99499SAndroid Build Coastguard Worker       .def("unit", &Benchmark::Unit, nb::rv_policy::reference)
77*dbb99499SAndroid Build Coastguard Worker       .def("arg", &Benchmark::Arg, nb::rv_policy::reference)
78*dbb99499SAndroid Build Coastguard Worker       .def("args", &Benchmark::Args, nb::rv_policy::reference)
79*dbb99499SAndroid Build Coastguard Worker       .def("range", &Benchmark::Range, nb::rv_policy::reference,
80*dbb99499SAndroid Build Coastguard Worker            nb::arg("start"), nb::arg("limit"))
81*dbb99499SAndroid Build Coastguard Worker       .def("dense_range", &Benchmark::DenseRange,
82*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference, nb::arg("start"),
83*dbb99499SAndroid Build Coastguard Worker            nb::arg("limit"), nb::arg("step") = 1)
84*dbb99499SAndroid Build Coastguard Worker       .def("ranges", &Benchmark::Ranges, nb::rv_policy::reference)
85*dbb99499SAndroid Build Coastguard Worker       .def("args_product", &Benchmark::ArgsProduct,
86*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
87*dbb99499SAndroid Build Coastguard Worker       .def("arg_name", &Benchmark::ArgName, nb::rv_policy::reference)
88*dbb99499SAndroid Build Coastguard Worker       .def("arg_names", &Benchmark::ArgNames,
89*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
90*dbb99499SAndroid Build Coastguard Worker       .def("range_pair", &Benchmark::RangePair,
91*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference, nb::arg("lo1"), nb::arg("hi1"),
92*dbb99499SAndroid Build Coastguard Worker            nb::arg("lo2"), nb::arg("hi2"))
93*dbb99499SAndroid Build Coastguard Worker       .def("range_multiplier", &Benchmark::RangeMultiplier,
94*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
95*dbb99499SAndroid Build Coastguard Worker       .def("min_time", &Benchmark::MinTime, nb::rv_policy::reference)
96*dbb99499SAndroid Build Coastguard Worker       .def("min_warmup_time", &Benchmark::MinWarmUpTime,
97*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
98*dbb99499SAndroid Build Coastguard Worker       .def("iterations", &Benchmark::Iterations,
99*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
100*dbb99499SAndroid Build Coastguard Worker       .def("repetitions", &Benchmark::Repetitions,
101*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
102*dbb99499SAndroid Build Coastguard Worker       .def("report_aggregates_only", &Benchmark::ReportAggregatesOnly,
103*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference, nb::arg("value") = true)
104*dbb99499SAndroid Build Coastguard Worker       .def("display_aggregates_only", &Benchmark::DisplayAggregatesOnly,
105*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference, nb::arg("value") = true)
106*dbb99499SAndroid Build Coastguard Worker       .def("measure_process_cpu_time", &Benchmark::MeasureProcessCPUTime,
107*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
108*dbb99499SAndroid Build Coastguard Worker       .def("use_real_time", &Benchmark::UseRealTime,
109*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
110*dbb99499SAndroid Build Coastguard Worker       .def("use_manual_time", &Benchmark::UseManualTime,
111*dbb99499SAndroid Build Coastguard Worker            nb::rv_policy::reference)
112*dbb99499SAndroid Build Coastguard Worker       .def(
113*dbb99499SAndroid Build Coastguard Worker           "complexity",
114*dbb99499SAndroid Build Coastguard Worker           (Benchmark * (Benchmark::*)(benchmark::BigO)) & Benchmark::Complexity,
115*dbb99499SAndroid Build Coastguard Worker           nb::rv_policy::reference,
116*dbb99499SAndroid Build Coastguard Worker           nb::arg("complexity") = benchmark::oAuto);
117*dbb99499SAndroid Build Coastguard Worker 
118*dbb99499SAndroid Build Coastguard Worker   using benchmark::Counter;
119*dbb99499SAndroid Build Coastguard Worker   nb::class_<Counter> py_counter(m, "Counter");
120*dbb99499SAndroid Build Coastguard Worker 
121*dbb99499SAndroid Build Coastguard Worker   nb::enum_<Counter::Flags>(py_counter, "Flags", nb::is_arithmetic())
122*dbb99499SAndroid Build Coastguard Worker       .value("kDefaults", Counter::Flags::kDefaults)
123*dbb99499SAndroid Build Coastguard Worker       .value("kIsRate", Counter::Flags::kIsRate)
124*dbb99499SAndroid Build Coastguard Worker       .value("kAvgThreads", Counter::Flags::kAvgThreads)
125*dbb99499SAndroid Build Coastguard Worker       .value("kAvgThreadsRate", Counter::Flags::kAvgThreadsRate)
126*dbb99499SAndroid Build Coastguard Worker       .value("kIsIterationInvariant", Counter::Flags::kIsIterationInvariant)
127*dbb99499SAndroid Build Coastguard Worker       .value("kIsIterationInvariantRate",
128*dbb99499SAndroid Build Coastguard Worker              Counter::Flags::kIsIterationInvariantRate)
129*dbb99499SAndroid Build Coastguard Worker       .value("kAvgIterations", Counter::Flags::kAvgIterations)
130*dbb99499SAndroid Build Coastguard Worker       .value("kAvgIterationsRate", Counter::Flags::kAvgIterationsRate)
131*dbb99499SAndroid Build Coastguard Worker       .value("kInvert", Counter::Flags::kInvert)
132*dbb99499SAndroid Build Coastguard Worker       .export_values()
133*dbb99499SAndroid Build Coastguard Worker       .def("__or__", [](Counter::Flags a, Counter::Flags b) {
134*dbb99499SAndroid Build Coastguard Worker         return static_cast<int>(a) | static_cast<int>(b);
135*dbb99499SAndroid Build Coastguard Worker       });
136*dbb99499SAndroid Build Coastguard Worker 
137*dbb99499SAndroid Build Coastguard Worker   nb::enum_<Counter::OneK>(py_counter, "OneK")
138*dbb99499SAndroid Build Coastguard Worker       .value("kIs1000", Counter::OneK::kIs1000)
139*dbb99499SAndroid Build Coastguard Worker       .value("kIs1024", Counter::OneK::kIs1024)
140*dbb99499SAndroid Build Coastguard Worker       .export_values();
141*dbb99499SAndroid Build Coastguard Worker 
142*dbb99499SAndroid Build Coastguard Worker   py_counter
143*dbb99499SAndroid Build Coastguard Worker       .def(
144*dbb99499SAndroid Build Coastguard Worker           "__init__",
145*dbb99499SAndroid Build Coastguard Worker           [](Counter* c, double value, int flags, Counter::OneK oneK) {
146*dbb99499SAndroid Build Coastguard Worker             new (c) Counter(value, static_cast<Counter::Flags>(flags), oneK);
147*dbb99499SAndroid Build Coastguard Worker           },
148*dbb99499SAndroid Build Coastguard Worker           nb::arg("value") = 0., nb::arg("flags") = Counter::kDefaults,
149*dbb99499SAndroid Build Coastguard Worker           nb::arg("k") = Counter::kIs1000)
150*dbb99499SAndroid Build Coastguard Worker       .def("__init__",
151*dbb99499SAndroid Build Coastguard Worker            ([](Counter* c, double value) { new (c) Counter(value); }))
152*dbb99499SAndroid Build Coastguard Worker       .def_rw("value", &Counter::value)
153*dbb99499SAndroid Build Coastguard Worker       .def_rw("flags", &Counter::flags)
154*dbb99499SAndroid Build Coastguard Worker       .def_rw("oneK", &Counter::oneK)
155*dbb99499SAndroid Build Coastguard Worker       .def(nb::init_implicit<double>());
156*dbb99499SAndroid Build Coastguard Worker 
157*dbb99499SAndroid Build Coastguard Worker   nb::implicitly_convertible<nb::int_, Counter>();
158*dbb99499SAndroid Build Coastguard Worker 
159*dbb99499SAndroid Build Coastguard Worker   nb::bind_map<benchmark::UserCounters>(m, "UserCounters");
160*dbb99499SAndroid Build Coastguard Worker 
161*dbb99499SAndroid Build Coastguard Worker   using benchmark::State;
162*dbb99499SAndroid Build Coastguard Worker   nb::class_<State>(m, "State")
163*dbb99499SAndroid Build Coastguard Worker       .def("__bool__", &State::KeepRunning)
164*dbb99499SAndroid Build Coastguard Worker       .def_prop_ro("keep_running", &State::KeepRunning)
165*dbb99499SAndroid Build Coastguard Worker       .def("pause_timing", &State::PauseTiming)
166*dbb99499SAndroid Build Coastguard Worker       .def("resume_timing", &State::ResumeTiming)
167*dbb99499SAndroid Build Coastguard Worker       .def("skip_with_error", &State::SkipWithError)
168*dbb99499SAndroid Build Coastguard Worker       .def_prop_ro("error_occurred", &State::error_occurred)
169*dbb99499SAndroid Build Coastguard Worker       .def("set_iteration_time", &State::SetIterationTime)
170*dbb99499SAndroid Build Coastguard Worker       .def_prop_rw("bytes_processed", &State::bytes_processed,
171*dbb99499SAndroid Build Coastguard Worker                     &State::SetBytesProcessed)
172*dbb99499SAndroid Build Coastguard Worker       .def_prop_rw("complexity_n", &State::complexity_length_n,
173*dbb99499SAndroid Build Coastguard Worker                     &State::SetComplexityN)
174*dbb99499SAndroid Build Coastguard Worker       .def_prop_rw("items_processed", &State::items_processed,
175*dbb99499SAndroid Build Coastguard Worker                    &State::SetItemsProcessed)
176*dbb99499SAndroid Build Coastguard Worker       .def("set_label", &State::SetLabel)
177*dbb99499SAndroid Build Coastguard Worker       .def("range", &State::range, nb::arg("pos") = 0)
178*dbb99499SAndroid Build Coastguard Worker       .def_prop_ro("iterations", &State::iterations)
179*dbb99499SAndroid Build Coastguard Worker       .def_prop_ro("name", &State::name)
180*dbb99499SAndroid Build Coastguard Worker       .def_rw("counters", &State::counters)
181*dbb99499SAndroid Build Coastguard Worker       .def_prop_ro("thread_index", &State::thread_index)
182*dbb99499SAndroid Build Coastguard Worker       .def_prop_ro("threads", &State::threads);
183*dbb99499SAndroid Build Coastguard Worker 
184*dbb99499SAndroid Build Coastguard Worker   m.def("Initialize", Initialize);
185*dbb99499SAndroid Build Coastguard Worker   m.def("RegisterBenchmark", RegisterBenchmark,
186*dbb99499SAndroid Build Coastguard Worker         nb::rv_policy::reference);
187*dbb99499SAndroid Build Coastguard Worker   m.def("RunSpecifiedBenchmarks",
188*dbb99499SAndroid Build Coastguard Worker         []() { benchmark::RunSpecifiedBenchmarks(); });
189*dbb99499SAndroid Build Coastguard Worker   m.def("ClearRegisteredBenchmarks", benchmark::ClearRegisteredBenchmarks);
190*dbb99499SAndroid Build Coastguard Worker };
191*dbb99499SAndroid Build Coastguard Worker }  // namespace
192