Subject: | Tests fail on OpenBSD with reasonably fast CPU |
In OpenBSD 6.2, on a 3.2ghz Xeon processor, I was getting test failures compiling perl 5.26.1 (and likely other versions).
I traced it down to this section of code and OpenBSD's clock() precision (which is at best MediumRes - CLOCKS_PER_SEC is 100). Basically, the existing delay loop (1e6 loops) was not enough to increment clock(). Indeed, clock() started test 5 at 0 (and ended it at 0).
Sample output from test five before the diff attached:
# clock = 0
# clock = 0 0
# clock = 0 0 0
# clock = 0 0 0 0
not ok 5
Sample output from test five after the diff attached:
# CLOCKS_PER_SEC = 100
# delay = 10000000
# clock = 0
# clock = 0 0.16
# clock = 0 0.16 0.32
# clock = 0 0.16 0.32 0.64
ok 5
I choose to implement this via a test for the initial value of clock(). If it gets to test 5 (having spent time on the other 4 tests) with a value less than 5 CLOCKS_PER_SEC, then I figure it's safe to have a delay of 1e7 instead of 1e6 - either the CPU is fast, the timer is relatively low precision, or it really is broken and the additional delay is probably okay in the case of a test failure. But this shouldn't make tests take longer anywhere that they succeeded in the past.
If you have different thoughts on how to solve this, please let me know.
diff -rc Time-HiRes-1.9752/t/clock.t Time-HiRes-1.9752.jtm/t/clock.t
*** Time-HiRes-1.9752/t/clock.t Sun Apr 16 02:33:09 2017
--- Time-HiRes-1.9752.jtm/t/clock.t Sat Jan 6 09:59:34 2018
***************
*** 80,88 ****
SKIP: {
skip "no clock", 1 unless &Time::HiRes::d_clock;
my @clock = Time::HiRes::clock();
print("# clock = @clock\n");
for my $i (1..3) {
! for (my $j = 0; $j < 1e6; $j++) { }
push @clock, Time::HiRes::clock();
print("# clock = @clock\n");
}
--- 80,93 ----
SKIP: {
skip "no clock", 1 unless &Time::HiRes::d_clock;
my @clock = Time::HiRes::clock();
+ # If we have a relatively low precision clock() and we haven't seen much
+ # CPU usage thus far with clock(), we will want to have a bit longer delay.
+ my $delay = $clock[0] < (5 / &Time::HiRes::CLOCKS_PER_SEC) ? 1e7 : 1e6;
+ printf("# CLOCKS_PER_SEC = %d\n", &Time::HiRes::CLOCKS_PER_SEC);
+ printf("# delay = %d\n", $delay);
print("# clock = @clock\n");
for my $i (1..3) {
! for (my $j = 0; $j < $delay; $j++) { }
push @clock, Time::HiRes::clock();
print("# clock = @clock\n");
}