Skip to content

Commit 663cd1a

Browse files
Bench with stack and heap data (#82)
* Bench with stack and heap data
1 parent 9483593 commit 663cd1a

File tree

4 files changed

+151
-47
lines changed

4 files changed

+151
-47
lines changed

.github/workflows/bench.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: bench
2+
3+
on:
4+
workflow_dispatch:
5+
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
cancel-in-progress: true
9+
10+
jobs:
11+
bench:
12+
name: Benchmarks
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Run Benchmarks
18+
run: make bench

.github/workflows/doc.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ on:
55
branches:
66
- master
77
paths-ignore:
8+
- '.devcontainer/**'
89
- '.vscode/**'
10+
- 'benchmarks/**'
11+
- 'tests/**'
912
- 'LICENSE'
13+
- 'Makefile'
1014
pull_request:
1115
paths-ignore:
16+
- '.devcontainer/**'
1217
- '.vscode/**'
18+
- 'benchmarks/**'
19+
- 'tests/**'
1320
- 'LICENSE'
21+
- 'Makefile'
1422
workflow_dispatch:
1523

1624
concurrency:

Makefile

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@ DOCS_DIR = docs
77
all:
88

99
bench:
10-
- sudo cpupower frequency-set --governor performance
11-
12-
rm -rf $(BENCH_DIR) && mkdir $(BENCH_DIR) && cd $(BENCH_DIR) \
10+
mkdir -p $(BENCH_DIR) && cd $(BENCH_DIR) \
1311
&& cmake ../.. -DCMAKE_BUILD_TYPE=Release -DCPP_CHANNEL_BUILD_BENCHMARKS=ON \
1412
&& cmake --build . --config Release --target channel_benchmark -j \
15-
&& ./benchmarks/channel_benchmark
16-
17-
- sudo cpupower frequency-set --governor powersave
13+
&& ./benchmarks/channel_benchmark \
14+
--benchmark_repetitions=10 \
15+
--benchmark_report_aggregates_only=true
1816

1917
coverage:
2018
rm -rf $(COV_DIR) && mkdir $(COV_DIR) && cd $(COV_DIR) \

benchmarks/channel_benchmark.cpp

Lines changed: 121 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,155 @@
22

33
#include <benchmark/benchmark.h>
44

5+
#include <array>
6+
#include <cstddef>
57
#include <string>
8+
#include <thread>
69

10+
// clang-format off
711
/**
812
Results on release build with CPU scaling disabled
913
c++ (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
1014
11-
2025-06-13T00:17:30+03:00
12-
Running ./tests/channel_benchmark
13-
Run on (8 X 3999.91 MHz CPU s)
15+
2025-06-17T19:55:02+03:00
16+
Running ./benchmarks/channel_benchmark
17+
Run on (8 X 4000.08 MHz CPU s)
1418
CPU Caches:
1519
L1 Data 32 KiB (x4)
1620
L1 Instruction 32 KiB (x4)
1721
L2 Unified 256 KiB (x4)
1822
L3 Unified 8192 KiB (x1)
19-
Load Average: 2.65, 1.61, 1.50
20-
------------------------------------------------------------------------------
21-
Benchmark Time CPU Iterations
22-
------------------------------------------------------------------------------
23-
channel_with_queue_storage 42602 ns 42598 ns 16407
24-
channel_with_vector_storage 42724 ns 42723 ns 16288
25-
channel_with_vector_storage 51332 ns 51328 ns 11776
23+
Load Average: 1.38, 1.22, 1.06
24+
------------------------------------------------------------------------------------------------------------------------------------------------------------
25+
Benchmark Time CPU Iterations
26+
------------------------------------------------------------------------------------------------------------------------------------------------------------
27+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<100000>>_mean 652607002 ns 226690848 ns 10
28+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<100000>>_median 651695229 ns 225379690 ns 10
29+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<100000>>_stddev 12253781 ns 15462972 ns 10
30+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<100000>>_cv 1.88 % 6.82 % 10
31+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<100000>>_max 672915805 ns 255534858 ns 10
32+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<100000>>_mean 974087950 ns 514260828 ns 10
33+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<100000>>_median 977160289 ns 516344216 ns 10
34+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<100000>>_stddev 18312948 ns 28280400 ns 10
35+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<100000>>_cv 1.88 % 5.50 % 10
36+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<100000>>_max 1003003285 ns 558790265 ns 10
37+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<100000>>_mean 628774895 ns 213404616 ns 10
38+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<100000>>_median 629143659 ns 215630841 ns 10
39+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<100000>>_stddev 8790540 ns 8340659 ns 10
40+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<100000>>_cv 1.40 % 3.91 % 10
41+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<100000>>_max 640584436 ns 224198673 ns 10
42+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<1000>>_mean 43353148 ns 33321779 ns 10
43+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<1000>>_median 43035735 ns 33114531 ns 10
44+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<1000>>_stddev 626857 ns 516438 ns 10
45+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<1000>>_cv 1.45 % 1.55 % 10
46+
bench_dynamic_storage<std::string, msd::queue_storage<std::string>, string_input<1000>>_max 44420815 ns 34055142 ns 10
47+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<1000>>_mean 143175350 ns 134608661 ns 10
48+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<1000>>_median 143349862 ns 135104870 ns 10
49+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<1000>>_stddev 9874397 ns 9112605 ns 10
50+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<1000>>_cv 6.90 % 6.77 % 10
51+
bench_dynamic_storage<std::string, msd::vector_storage<std::string>, string_input<1000>>_max 160931701 ns 149620486 ns 10
52+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<1000>>_mean 37482750 ns 36598866 ns 10
53+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<1000>>_median 37678000 ns 36697213 ns 10
54+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<1000>>_stddev 972055 ns 739164 ns 10
55+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<1000>>_cv 2.59 % 2.02 % 10
56+
bench_static_storage<std::string, msd::array_storage<std::string, channel_capacity>, string_input<1000>>_max 38740257 ns 37767023 ns 10
57+
bench_dynamic_storage<data, msd::queue_storage<data>, struct_input>_mean 56195102 ns 37959789 ns 10
58+
bench_dynamic_storage<data, msd::queue_storage<data>, struct_input>_median 56222959 ns 37916027 ns 10
59+
bench_dynamic_storage<data, msd::queue_storage<data>, struct_input>_stddev 239106 ns 192415 ns 10
60+
bench_dynamic_storage<data, msd::queue_storage<data>, struct_input>_cv 0.43 % 0.51 % 10
61+
bench_dynamic_storage<data, msd::queue_storage<data>, struct_input>_max 56524553 ns 38392052 ns 10
62+
bench_dynamic_storage<data, msd::vector_storage<data>, struct_input>_mean 318745363 ns 299820882 ns 10
63+
bench_dynamic_storage<data, msd::vector_storage<data>, struct_input>_median 333031832 ns 312967363 ns 10
64+
bench_dynamic_storage<data, msd::vector_storage<data>, struct_input>_stddev 30118977 ns 28236407 ns 10
65+
bench_dynamic_storage<data, msd::vector_storage<data>, struct_input>_cv 9.45 % 9.42 % 10
66+
bench_dynamic_storage<data, msd::vector_storage<data>, struct_input>_max 343551976 ns 323198986 ns 10
67+
bench_static_storage<data, msd::array_storage<data, channel_capacity>, struct_input>_mean 39037187 ns 32142886 ns 10
68+
bench_static_storage<data, msd::array_storage<data, channel_capacity>, struct_input>_median 39015373 ns 32017939 ns 10
69+
bench_static_storage<data, msd::array_storage<data, channel_capacity>, struct_input>_stddev 557539 ns 701550 ns 10
70+
bench_static_storage<data, msd::array_storage<data, channel_capacity>, struct_input>_cv 1.43 % 2.18 % 10
71+
bench_static_storage<data, msd::array_storage<data, channel_capacity>, struct_input>_max 40336146 ns 33191282 ns 10
2672
*/
73+
// clang-format on
2774

28-
static void channel_with_queue_storage(benchmark::State& state)
29-
{
30-
msd::channel<std::string, msd::queue_storage<std::string>> channel{10};
75+
static constexpr std::size_t channel_capacity = 1024;
76+
static constexpr std::size_t number_of_inputs = 100000;
3177

32-
std::string input(1000000, 'x');
33-
std::string out{};
34-
out.resize(input.size());
78+
template <std::size_t Size>
79+
struct string_input {
80+
static std::string make() { return std::string(Size, 'c'); }
81+
};
3582

36-
for (auto _ : state) {
37-
benchmark::DoNotOptimize(channel << input);
38-
benchmark::DoNotOptimize(channel >> out);
39-
}
40-
}
83+
struct data {
84+
std::array<int, 1000> data{};
85+
};
4186

42-
BENCHMARK(channel_with_queue_storage);
87+
struct struct_input {
88+
static data make() { return data{}; }
89+
};
4390

44-
static void channel_with_vector_storage(benchmark::State& state)
91+
template <typename T, typename Storage, typename Input>
92+
static void bench_dynamic_storage(benchmark::State& state)
4593
{
46-
msd::channel<std::string, msd::vector_storage<std::string>> channel{10};
47-
48-
std::string input(1000000, 'x');
49-
std::string out{};
50-
out.resize(input.size());
94+
const auto input = Input::make();
5195

5296
for (auto _ : state) {
53-
benchmark::DoNotOptimize(channel << input);
54-
benchmark::DoNotOptimize(channel >> out);
97+
msd::channel<T, Storage> channel{channel_capacity};
98+
99+
std::thread producer([&] {
100+
for (std::size_t i = 0; i < number_of_inputs; ++i) {
101+
channel << input;
102+
}
103+
channel.close();
104+
});
105+
106+
for (auto& value : channel) {
107+
volatile auto* do_not_optimize = &value;
108+
(void)do_not_optimize;
109+
}
110+
111+
producer.join();
55112
}
56113
}
57114

58-
BENCHMARK(channel_with_vector_storage);
59-
60-
static void channel_with_array_storage(benchmark::State& state)
115+
template <typename T, typename Storage, typename Input>
116+
static void bench_static_storage(benchmark::State& state)
61117
{
62-
msd::channel<std::string, msd::array_storage<std::string, 10>> channel{};
63-
64-
std::string input(1000000, 'x');
65-
std::string out{};
66-
out.resize(input.size());
118+
const auto input = Input::make();
67119

68120
for (auto _ : state) {
69-
benchmark::DoNotOptimize(channel << input);
70-
benchmark::DoNotOptimize(channel >> out);
121+
msd::channel<T, Storage> channel{};
122+
123+
std::thread producer([&] {
124+
for (std::size_t i = 0; i < number_of_inputs; ++i) {
125+
channel << input;
126+
}
127+
channel.close();
128+
});
129+
130+
for (auto& value : channel) {
131+
volatile auto* do_not_optimize = &value;
132+
(void)do_not_optimize;
133+
}
134+
135+
producer.join();
71136
}
72137
}
73138

74-
BENCHMARK(channel_with_array_storage);
139+
#define BENCH(...) \
140+
BENCHMARK_TEMPLATE(__VA_ARGS__)->ComputeStatistics("max", [](const std::vector<double>& v) { \
141+
return *std::max_element(v.begin(), v.end()); \
142+
})
143+
144+
BENCH(bench_dynamic_storage, std::string, msd::queue_storage<std::string>, string_input<100000>);
145+
BENCH(bench_dynamic_storage, std::string, msd::vector_storage<std::string>, string_input<100000>);
146+
BENCH(bench_static_storage, std::string, msd::array_storage<std::string, channel_capacity>, string_input<100000>);
147+
148+
BENCH(bench_dynamic_storage, std::string, msd::queue_storage<std::string>, string_input<1000>);
149+
BENCH(bench_dynamic_storage, std::string, msd::vector_storage<std::string>, string_input<1000>);
150+
BENCH(bench_static_storage, std::string, msd::array_storage<std::string, channel_capacity>, string_input<1000>);
151+
152+
BENCH(bench_dynamic_storage, data, msd::queue_storage<data>, struct_input);
153+
BENCH(bench_dynamic_storage, data, msd::vector_storage<data>, struct_input);
154+
BENCH(bench_static_storage, data, msd::array_storage<data, channel_capacity>, struct_input);
75155

76156
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)