-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmark.cpp
More file actions
104 lines (90 loc) · 2.78 KB
/
benchmark.cpp
File metadata and controls
104 lines (90 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "spsc_queue.hpp"
#include <sched.h>
#include <thread>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <chrono>
void pin_thread(int cpu)
{
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(cpu, &cpu_set);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu_set) == -1)
{
perror("pthread_setaffinity_np failed. \n");
exit(EXIT_FAILURE);
}
}
double median(std::vector<int64_t> &res)
{
size_t k = res.size() / 2;
std::nth_element(begin(res), begin(res) + k, end(res));
double m = res[k];
if (k & 1)
return m;
std::nth_element(begin(res), begin(res) + k - 1, end(res));
return (m + res[k - 1]) * 0.5;
}
void print_metrics(std::vector<int64_t> &res)
{
int64_t sum = std::accumulate(begin(res), end(res), int64_t{0});
const char *unit = " elements/s \n";
std::cout << std::fixed;
std::cout.imbue(std::locale("en_US.utf8"));
std::cout << "Mean: " << sum / static_cast<double>(res.size()) << unit;
std::cout << "Median: " << median(res) << unit;
std::cout << "Max: " << *std::max_element(begin(res), end(res)) << unit;
std::cout << "Min: " << *std::min_element(begin(res), end(res)) << unit;
}
void run_benchmark(int cpu_consumer, int cpu_producer, int iterations)
{
std::vector<int64_t> res(iterations, 0);
constexpr int capacity = int(1 << 16);
constexpr int elements = int(1e8);
for (int iter = 0; iter < iterations; ++iter)
{
spsc_queue<int> sq(capacity);
auto consumer = [&]
{
pin_thread(cpu_consumer);
for (int i = 0; i < elements; ++i)
{
int item = -1;
while (!sq.dequeue(item))
;
if (item != i)
{
std::printf("Dequeue failed: expected = %d, but got %d \n", i, item);
exit(EXIT_FAILURE);
}
}
};
// start consumer thread
std::thread th_consumer(consumer);
// producer is current main thread
pin_thread(cpu_producer);
auto start = std::chrono::steady_clock::now();
{
for (int i = 0; i < elements; i++)
{
while (!sq.enqueue(i))
;
}
// wait until the consumer dequeues all the items
while (!sq.empty())
;
}
const std::chrono::duration<double> diff = std::chrono::steady_clock::now() - start; // in seconds
th_consumer.join();
res[iter] = elements * double{1.0} / diff.count();
}
print_metrics(res);
}
int main()
{
constexpr int cpu1 = 1;
constexpr int cpu2 = 3;
constexpr int iterations = 10;
run_benchmark(cpu1, cpu2, iterations);
}