mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 10:54:07 +08:00
[libstdc++-v3] [testsuite] improve future/*/poll.cc calibration
30_threads/future/members/poll.cc has calibration code that, on systems with very low clock resolution, may spuriously fail to run. Even when it does run, low resolution and reasonable timeouts limit severely the viability of increasing the loop counts so as to reduce measurement noise, so we end up with very noisy results. On various vxworks targets, high iteration count (low-noise) measurements confirmed that some of the operations that we expected to be up to 100x slower than the fastest ones can run a little slower than that and, with significant noise, may seem to be even slower, comparatively. Bump the factors up to 200x, so that we have plenty of margin over measured results. for libstdc++-v3/ChangeLog * testsuite/30_threads/future/members/poll.cc: Factor out calibration, and run it unconditionally. Lower its strictness. Bump wait_until_*'s slowness factor.
This commit is contained in:
parent
410061b15a
commit
af1500dd8c
@ -41,52 +41,75 @@ print(const char* desc, Duration dur)
|
||||
return d;
|
||||
}
|
||||
|
||||
static void
|
||||
calibrate()
|
||||
{
|
||||
/* After set_value, wait_for is faster, so use that for the
|
||||
calibration loops to avoid zero at low clock resultions. */
|
||||
promise<int> p = {};
|
||||
future<int> f = p.get_future();
|
||||
p.set_value(1);
|
||||
|
||||
auto start = chrono::high_resolution_clock::now();
|
||||
auto stop = start;
|
||||
/* Loop until the clock advances, so that start is right after a
|
||||
time increment. */
|
||||
do
|
||||
stop = chrono::high_resolution_clock::now();
|
||||
while (start == stop);
|
||||
|
||||
/* This approximates the smallest time increment we may expect to be
|
||||
able to measure. It doesn't have to be very precise, just a
|
||||
ballpart of the right magnitude. */
|
||||
auto tick = stop - start;
|
||||
|
||||
int i = 0;
|
||||
start = stop;
|
||||
/* Now until the clock advances again, so that stop is right
|
||||
after another time increment. */
|
||||
do
|
||||
{
|
||||
f.wait_for(chrono::seconds(0));
|
||||
stop = chrono::high_resolution_clock::now();
|
||||
i++;
|
||||
}
|
||||
while (start == stop);
|
||||
|
||||
/* Aim for some 10 ticks. This won't be quite right if now() takes
|
||||
up a significant portion of the loop time, but we'll measure
|
||||
without that and adjust in the loop below. */
|
||||
if (iterations < i * 10)
|
||||
iterations = i * 10;
|
||||
|
||||
/* We aim for some 10 ticks for the loop that's expected to be fastest,
|
||||
but even if we don't get quite that many, we're still fine. */
|
||||
iterations /= 2;
|
||||
do
|
||||
{
|
||||
iterations *= 2;
|
||||
start = chrono::high_resolution_clock::now();
|
||||
for(int i = 0; i < iterations; i++)
|
||||
f.wait_for(chrono::seconds(0));
|
||||
stop = chrono::high_resolution_clock::now();
|
||||
}
|
||||
while (stop - start < 5 * tick);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
/* First, calibrate the iteration count so that we don't get any of
|
||||
the actual measurement loops to complete in less than the clock
|
||||
granularity. */
|
||||
calibrate ();
|
||||
|
||||
promise<int> p;
|
||||
future<int> f = p.get_future();
|
||||
|
||||
start_over:
|
||||
auto start = chrono::high_resolution_clock::now();
|
||||
for(int i = 0; i < iterations; i++)
|
||||
f.wait_for(chrono::seconds(0));
|
||||
auto stop = chrono::high_resolution_clock::now();
|
||||
|
||||
/* We've run too few iterations for the clock resolution.
|
||||
Attempt to calibrate it. */
|
||||
if (start == stop)
|
||||
{
|
||||
/* After set_value, wait_for is faster, so use that for the
|
||||
calibration to avoid zero at low clock resultions. */
|
||||
promise<int> pc;
|
||||
future<int> fc = pc.get_future();
|
||||
pc.set_value(1);
|
||||
|
||||
/* Loop until the clock advances, so that start is right after a
|
||||
time increment. */
|
||||
do
|
||||
start = chrono::high_resolution_clock::now();
|
||||
while (start == stop);
|
||||
int i = 0;
|
||||
/* Now until the clock advances again, so that stop is right
|
||||
after another time increment. */
|
||||
do
|
||||
{
|
||||
fc.wait_for(chrono::seconds(0));
|
||||
stop = chrono::high_resolution_clock::now();
|
||||
i++;
|
||||
}
|
||||
while (start == stop);
|
||||
/* Go for some 10 cycles, but if we're already past that and
|
||||
still get into the calibration loop, double the iteration
|
||||
count and try again. */
|
||||
if (iterations < i * 10)
|
||||
iterations = i * 10;
|
||||
else
|
||||
iterations *= 2;
|
||||
goto start_over;
|
||||
}
|
||||
|
||||
double wait_for_0 = print("wait_for(0s)", stop - start);
|
||||
|
||||
start = chrono::high_resolution_clock::now();
|
||||
@ -129,15 +152,21 @@ int main()
|
||||
// after the result is ready.
|
||||
VERIFY( wait_for_0 < (ready * 30) );
|
||||
|
||||
// Polling before ready using wait_until(min) should not be terribly slow.
|
||||
VERIFY( wait_until_sys_min < (ready * 100) );
|
||||
VERIFY( wait_until_steady_min < (ready * 100) );
|
||||
// Polling before ready using wait_until(min) should not be terribly
|
||||
// slow. We hope for no more than 100x slower, but a little over
|
||||
// 100x has been observed, and since the measurements may have a lot
|
||||
// of noise, and increasing the measurement precision through
|
||||
// additional iterations would make the test run for too long on
|
||||
// systems with very low clock precision (60Hz clocks are not
|
||||
// unheard of), we tolerate a lot of error.
|
||||
VERIFY( wait_until_sys_min < (ready * 200) );
|
||||
VERIFY( wait_until_steady_min < (ready * 200) );
|
||||
|
||||
// The following two tests fail with GCC 11, see
|
||||
// https://gcc.gnu.org/pipermail/libstdc++/2020-November/051422.html
|
||||
#if 0
|
||||
// Polling before ready using wait_until(epoch) should not be terribly slow.
|
||||
VERIFY( wait_until_sys_epoch < (ready * 100) );
|
||||
VERIFY( wait_until_steady_epoch < (ready * 100) );
|
||||
VERIFY( wait_until_sys_epoch < (ready * 200) );
|
||||
VERIFY( wait_until_steady_epoch < (ready * 200) );
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user