#Header
#include "co/benchmark.h"
#API
There is only one public function, in the co namespace:
void co::run_benchmarks();
- Run benchmarks; results are output in markdown table format.
mainis generally written in a fixed way:
#include "co/benchmark.h"
int main(int argc, char** argv) {
flag::parse(argc, argv);
co::run_benchmarks();
return 0;
}
#Defining a Benchmark Group
BM_group(name) {
// BM_add(...) { ... }
}
- The
BM_groupmacro defines a benchmark group. It is actually a function, and users can freely add common initialization code, warm-up code, etc. inside it; namemust be a valid variable name;- When there are multiple
BM_groups,namemust not be duplicated.
#Defining a Benchmark Case
BM_add(name) {
// test code
}
- The
BM_addmacro defines a benchmark case. It is actually a code block inside the function defined byBM_group; nameis not required to be a valid variable name;
#Subgroups
BM_sub_group_begin;
- Start a subgroup inside
BM_group; subgroups are compared independently. BM_addbefore the firstBM_sub_group_beginbelongs to the default subgroup.- Each subgroup uses the first test as the baseline, and the remaining tests calculate
speeduprelative to that baseline. - The baseline itself displays
speedupas-.
#BM_use
BM_use(v);
- Prevent the compiler from optimizing away the test code.
- If the test code is optimized away,
iters/swill be abnormally large; in this case,BM_usecan be used. - It can be used for any variable and is usually placed outside
BM_addto avoid interfering with the code under test.
#Running Logic
- Each
BM_groupinternally defines a bool flag with a default value offalse. - If the flags of all groups are at their default values, all groups are run.
- If any flag is
true, only groups whose flag istrueare run. - Groups are executed in registration order.
Command-line example:
./xx # Run all groups
./xx -rand # Run only the rand group
./xx -rand -log # Run only the rand and log groups
#Example
#include "co/benchmark.h"
#include "co/atomic.h"
#include "co/rand.h"
#include <random>
BM_group(atomic) {
__cacheline_aligned int i = 0;
BM_add(atomic_inc) {
co::atomic_inc(&i);
}
BM_use(i);
BM_add(atomic_dec) {
co::atomic_dec(&i);
}
BM_use(i);
BM_add(atomic_cas) {
co::atomic_cas(&i, 0, 1);
}
BM_use(i);
BM_add(atomic_or) {
co::atomic_or(&i, 11);
}
BM_use(i);
}
BM_group(rand) {
// Warm up
uint32 x = ::rand();
x += co::rand();
BM_sub_group_begin;
BM_add(::rand) {
x = ::rand();
}
BM_use(x);
BM_add(co::rand) {
x = co::rand();
}
BM_use(x);
uint32 seed = co::rand();
BM_add(co::rand(seed)) {
x = co::rand(seed);
}
BM_use(x);
std::mt19937 m(std::random_device{}());
BM_add(std::mt19937) {
x = m();
}
BM_use(x);
uint64 u;
BM_add(co::rand64) {
u = co::rand64();
}
BM_use(u);
uint64 seed64 = co::rand64();
BM_add(co::rand64(seed)) {
u = co::rand64(seed64);
}
BM_use(u);
BM_sub_group_begin;
BM_add(co::randstr) {
(void)co::randstr();
}
BM_add(co::randstr(charsets)) {
(void) co::randstr("0-9a-f", 15);
}
char buf[16];
BM_add(co::randchars) {
co::randchars(buf, sizeof(buf));
}
BM_use(buf);
}
int main(int argc, char** argv) {
flag::parse(argc, argv);
co::run_benchmarks();
return 0;
}
Run:
./bm # Run atomic and rand
./bm -atomic # Run only atomic
./bm -rand # Run only rand
Test results:

- The output is in Markdown table format.
ns/iter: nanoseconds per iteration.iters/s: iterations per second.speedup: speedup factor relative to the test baseline.
#Building and Running coost Internal Benchmarks
The benchmark directory contains coost’s internal benchmark code. Execute the following commands in the coost root directory to build and run:
# Build
xmake b benchmark
# Run all benchmark code by default
xmake r benchmark
# Run only the specified benchmarks
xmake r benchmark -rand -mem