Skip to content

Commit 46dd75d

Browse files
committed
test: add retry logic for eventloopdelay histogram sampling
On some build configurations (e.g., sharedlibs), the histogram may not record valid samples (min > 0) after the initial spinning period. This adds a retry mechanism that will spin the event loop additional times if valid samples haven't been recorded yet. This helps ensure the test passes on slower or differently-configured systems where event loop delay sampling may take longer to produce measurable results. Refs: nodejs/reliability#1461
1 parent 3b69757 commit 46dd75d

1 file changed

Lines changed: 62 additions & 44 deletions

File tree

test/sequential/test-performance-eventloopdelay.js

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -52,59 +52,77 @@ const { sleep } = require('internal/util');
5252
}
5353

5454
{
55-
const s390x = os.arch() === 's390x';
5655
const histogram = monitorEventLoopDelay({ resolution: 1 });
5756
histogram.enable();
58-
let m = 5;
59-
if (s390x) {
60-
m = m * 2;
57+
58+
// Check if histogram has recorded valid samples (min > 0 indicates real delays measured)
59+
function hasValidSamples() {
60+
return histogram.count > 0 && histogram.min > 0 && histogram.max > 0;
6161
}
62+
63+
// Spin the event loop with blocking work to generate measurable delays.
64+
// Some configurations (s390x, sharedlibs) need more iterations.
65+
let spinsRemaining = 5;
66+
const maxRetries = 3;
67+
let retries = 0;
68+
6269
function spinAWhile() {
6370
sleep(1000);
64-
if (--m > 0) {
71+
if (--spinsRemaining > 0) {
6572
setTimeout(spinAWhile, common.platformTimeout(500));
6673
} else {
67-
// Give the histogram a chance to record final samples before disabling.
68-
// This helps on slower systems where sampling may be delayed.
69-
setImmediate(common.mustCall(() => {
70-
histogram.disable();
71-
// The values are non-deterministic, so we just check that a value is
72-
// present, as opposed to a specific value.
73-
assert(histogram.count > 0, `Expected samples to be recorded, got count=${histogram.count}`);
74-
assert(histogram.min > 0);
75-
assert(histogram.max > 0);
76-
assert(histogram.stddev > 0);
77-
assert(histogram.mean > 0);
78-
assert(histogram.percentiles.size > 0);
79-
for (let n = 1; n < 100; n = n + 0.1) {
80-
assert(histogram.percentile(n) >= 0);
74+
// Give the histogram a chance to record final samples before checking.
75+
setImmediate(() => {
76+
// If we don't have valid samples yet, retry with more spinning.
77+
// This handles slower configurations like sharedlibs builds.
78+
if (!hasValidSamples() && retries < maxRetries) {
79+
retries++;
80+
spinsRemaining = 5;
81+
setTimeout(spinAWhile, common.platformTimeout(500));
82+
return;
8183
}
82-
histogram.reset();
83-
assert.strictEqual(histogram.min, 9223372036854776000);
84-
assert.strictEqual(histogram.max, 0);
85-
assert(Number.isNaN(histogram.stddev));
86-
assert(Number.isNaN(histogram.mean));
87-
assert.strictEqual(histogram.percentiles.size, 1);
8884

89-
['a', false, {}, []].forEach((i) => {
90-
assert.throws(
91-
() => histogram.percentile(i),
92-
{
93-
name: 'TypeError',
94-
code: 'ERR_INVALID_ARG_TYPE',
95-
}
96-
);
97-
});
98-
[-1, 0, 101, NaN].forEach((i) => {
99-
assert.throws(
100-
() => histogram.percentile(i),
101-
{
102-
name: 'RangeError',
103-
code: 'ERR_OUT_OF_RANGE',
104-
}
105-
);
106-
});
107-
}));
85+
// Wrap final assertions in mustCall to ensure they run
86+
common.mustCall(() => {
87+
histogram.disable();
88+
// The values are non-deterministic, so we just check that a value is
89+
// present, as opposed to a specific value.
90+
assert(histogram.count > 0, `Expected samples to be recorded, got count=${histogram.count}`);
91+
assert(histogram.min > 0, `Expected min > 0, got ${histogram.min}`);
92+
assert(histogram.max > 0);
93+
assert(histogram.stddev > 0);
94+
assert(histogram.mean > 0);
95+
assert(histogram.percentiles.size > 0);
96+
for (let n = 1; n < 100; n = n + 0.1) {
97+
assert(histogram.percentile(n) >= 0);
98+
}
99+
histogram.reset();
100+
assert.strictEqual(histogram.min, 9223372036854776000);
101+
assert.strictEqual(histogram.max, 0);
102+
assert(Number.isNaN(histogram.stddev));
103+
assert(Number.isNaN(histogram.mean));
104+
assert.strictEqual(histogram.percentiles.size, 1);
105+
106+
['a', false, {}, []].forEach((i) => {
107+
assert.throws(
108+
() => histogram.percentile(i),
109+
{
110+
name: 'TypeError',
111+
code: 'ERR_INVALID_ARG_TYPE',
112+
}
113+
);
114+
});
115+
[-1, 0, 101, NaN].forEach((i) => {
116+
assert.throws(
117+
() => histogram.percentile(i),
118+
{
119+
name: 'RangeError',
120+
code: 'ERR_OUT_OF_RANGE',
121+
}
122+
);
123+
});
124+
})();
125+
});
108126
}
109127
}
110128
spinAWhile();

0 commit comments

Comments
 (0)