FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
thread/example/perf_condition_variable.cpp at develop · boostorg/thread · GitHub
boostorg
thread
Repository navigation
Code
Issues
77
(77)
Pull requests
13
(13)
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
thread
/
example
/
perf_condition_variable.cpp
Copy path
More file actions
More file actions
Latest commit
History
History
History
237 lines (196 loc) · 6.66 KB
Breadcrumbs
thread
/
example
/
perf_condition_variable.cpp
Copy path
File metadata and controls
237 lines (196 loc) · 6.66 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//
(C) Copyright 2012 Vicente J. Botet Escriba
//
//
Distributed under the Boost Software License, Version 1.0. (See
//
accompanying file LICENSE_1_0.txt or copy at
//
http://www.boost.org/LICENSE_1_0.txt)
//
//
This performance test is based on the performance test provided by maxim.yegorushkin
//
at https://svn.boost.org/trac/boost/ticket/7422
#
define
BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
#
include
<
boost/thread/condition_variable.hpp
>
#
include
<
boost/thread/mutex.hpp
>
#
include
<
boost/chrono/stopwatches/simple_stopwatch.hpp
>
#
include
<
condition_variable
>
#
include
<
future
>
#
include
<
limits
>
#
include
<
cstdio
>
#
include
<
thread
>
#
include
<
mutex
>
#
include
<
vector
>
//
//////////////////////////////////////////////////////////////////////////////////////////////
namespace
{
//
//////////////////////////////////////////////////////////////////////////////////////////////
//
class Stopwatch
//
{
//
public:
//
typedef long long rep;
//
//
static rep now()
//
{
//
timespec ts;
//
if (clock_gettime(CLOCK_MONOTONIC, &ts)) abort();
//
return ts.tv_sec * rep(1000000000) + ts.tv_nsec;
//
}
//
//
Stopwatch() :
//
start_(now())
//
{
//
}
//
//
rep elapsed() const
//
{
//
return now() - start_;
//
}
//
//
private:
//
rep start_;
//
};
typedef
boost::chrono::simple_stopwatch<> Stopwatch;
//
//////////////////////////////////////////////////////////////////////////////////////////////
struct
BoostTypes
{
typedef
boost::condition_variable condition_variable;
typedef
boost::mutex mutex;
typedef
boost::mutex::scoped_lock scoped_lock;
};
struct
StdTypes
{
typedef
std::condition_variable condition_variable;
typedef
std::mutex mutex;
typedef
std::unique_lock<std::mutex> scoped_lock;
};
template
<
class
Types
>
struct
SharedData
: Types
{
unsigned
const
iterations;
unsigned
counter;
unsigned
semaphore;
typename
Types::condition_variable cnd;
typename
Types::mutex mtx;
Stopwatch::rep producer_time;
SharedData
(
unsigned
iterations,
unsigned
consumers) :
iterations
(iterations), counter(), semaphore(consumers)
//
Initialize to the number of consumers. (*)
, producer_time()
{
}
};
//
//////////////////////////////////////////////////////////////////////////////////////////////
template
<
class
S
>
void
producer_thread
(S* shared_data)
{
Stopwatch sw;
unsigned
const
consumers = shared_data->
semaphore
;
//
(*)
for
(
unsigned
i = shared_data->
iterations
; i--;)
{
{
typename
S::scoped_lock
lock
(shared_data->
mtx
);
//
Wait till all consumers signal.
while
(consumers != shared_data->
semaphore
)
{
shared_data->
cnd
.
wait
(lock);
}
shared_data->
semaphore
=
0
;
//
Signal consumers.
++shared_data->
counter
;
}
shared_data->
cnd
.
notify_all
();
}
shared_data->
producer_time
= sw.
elapsed
().
count
();
}
template
<
class
S
>
void
consumer_thread
(S* shared_data)
{
unsigned
counter =
0
;
while
(counter != shared_data->
iterations
)
{
{
typename
S::scoped_lock
lock
(shared_data->
mtx
);
//
Wait till the producer signals.
while
(counter == shared_data->
counter
)
{
shared_data->
cnd
.
wait
(lock);
}
counter = shared_data->
counter
;
//
Signal the producer.
++shared_data->
semaphore
;
}
shared_data->
cnd
.
notify_all
();
}
}
//
//////////////////////////////////////////////////////////////////////////////////////////////
template
<
class
Types
>
Stopwatch::rep
benchmark_ping_pong
(
unsigned
consumer_count)
{
typedef
SharedData<Types> S;
auto
best_producer_time = std::numeric_limits<Stopwatch::rep>::max
BOOST_PREVENT_MACRO_SUBSTITUTION
();
std::vector<std::thread> consumers
{ consumer_count };
//
Run the benchmark 10 times and report the best time.
for
(
int
times =
10
; times--;)
{
S shared_data
{
100000
, consumer_count };
//
Start the consumers.
for
(
unsigned
i =
0
; i < consumer_count; ++i)
consumers[i] = std::thread
{ consumer_thread<S> , &shared_data };
//
Start the producer and wait till it finishes.
std::thread
{ producer_thread<S> , &shared_data }.
join
();
//
Wait till consumers finish.
for
(
unsigned
i =
0
; i < consumer_count; ++i)
consumers[i].
join
();
best_producer_time = std::min
BOOST_PREVENT_MACRO_SUBSTITUTION
(best_producer_time, shared_data.
producer_time
);
}
return
best_producer_time;
}
//
//////////////////////////////////////////////////////////////////////////////////////////////
}
//
namespace
//
//////////////////////////////////////////////////////////////////////////////////////////////
//
sudo chrt -f 99 /usr/bin/time -f "\n***\ntime: %E\ncontext switches: %c\nwaits: %w" /home/max/otsquant/build/Linux-x86_64-64.g++-release/test/test
/*
Producer-consumer ping-pong tests. It aims to benchmark condition variables with and without
thread cancellation support by comparing the time it took to complete the benchmark.
Condition variable with thread cancellation support is boost::condition_variable from
boost-1.51. Without - std::condition_variable that comes with gcc-4.7.2.
One producer, one to CONSUMER_MAX consumers. The benchmark calls
condition_variable::notify_all() without holding a mutex to maximize contention within this
function. Each benchmark for a number of consumers is run three times and the best time is
picked to get rid of outliers.
The results are reported for each benchmark for a number of consumers. The most important number
is (std - boost) / std * 100. Positive numbers are when boost::condition_variable is faster,
negative it is slower.
*/
int
main
()
{
std::printf
(
"
MAIN
\n
"
);
enum
{
CONSUMER_MAX
=
2
};
struct
{
Stopwatch::rep boost, std;
} best_times[
CONSUMER_MAX
] = {};
for
(
unsigned
i =
1
; i <=
CONSUMER_MAX
; ++i)
{
auto
& b = best_times[i -
1
];
std::printf
(
"
STD: %d
\n
"
, i);
b.
std
= benchmark_ping_pong<StdTypes> (i);
std::printf
(
"
BOOST: %d
\n
"
, i);
b.
boost
= benchmark_ping_pong<BoostTypes> (i);
std::printf
(
"
consumers: %4d
\n
"
, i);
std::printf
(
"
best std producer time: %15.9fsec
\n
"
, b.
std
*
1e-9
);
std::printf
(
"
best boost producer time: %15.9fsec
\n
"
, b.
boost
*
1e-9
);
std::printf
(
"
(std - boost) / std: %7.2f%%
\n
"
, (b.
std
- b.
boost
) *
100
. / b.
std
);
}
printf
(
"
\n
csv:
\n\n
"
);
printf
(
"
consumers,(std-boost)/std,std,boost
\n
"
);
for
(
unsigned
i =
1
; i <=
CONSUMER_MAX
; ++i)
{
auto
& b = best_times[i -
1
];
printf
(
"
%d,%f,%lld,%lld
\n
"
, i, (b.
std
- b.
boost
) *
100
. / b.
std
, b.
std
, b.
boost
);
}
return
1
;
}
Back
|
FazBrowse Home
|
New Git URL