mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
test(perf): refuse a J1 idle window that opened late after the settle point
Addresses review: the idle window opens in the settle timer's callback while the settle point is that timer's deadline, so a late callback left ticks uncounted between the two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
454c1fe10a
commit
7e383ca675
3 files changed
+44
-8
No files matched your search
@@ -31,8 +31,8 @@ function measurement(
|
||||
firstCardPaintEpochMs: 2_650,
|
||||
idle: {
|
||||
domMutations: 12,
|
||||
endEpochMs: 36_000.04,
|
||||
startEpochMs: 6_000,
|
||||
endEpochMs: 33_200.04,
|
||||
startEpochMs: 3_200,
|
||||
status: 'done',
|
||||
ticks: 31,
|
||||
},
|
||||
@@ -198,7 +198,7 @@ test('maps the probe, IPC capture and main counters to exact counters and spawn-
|
||||
assert.deepEqual(record.evidence['idle'], {
|
||||
domMutations: 12,
|
||||
durationMs: 30_000,
|
||||
settledToIdleStartMs: 2_819.9,
|
||||
settledToIdleStartMs: 19.9,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -278,14 +278,32 @@ test('refuses a launch without a complete, on-time idle window after the settle
|
||||
),
|
||||
/idle-before-settle/
|
||||
);
|
||||
// The settle point is 3_180.06: a window opened 120 ms after it left
|
||||
// ticks uncounted in between.
|
||||
assert.throws(
|
||||
() =>
|
||||
toLaunchIterationRecord(0, false, withIdle({ endEpochMs: 35_000 })),
|
||||
toLaunchIterationRecord(
|
||||
0,
|
||||
false,
|
||||
withIdle({ endEpochMs: 33_300.1, startEpochMs: 3_300.1 })
|
||||
),
|
||||
/idle-start-late/
|
||||
);
|
||||
assert.doesNotThrow(() =>
|
||||
toLaunchIterationRecord(
|
||||
0,
|
||||
false,
|
||||
withIdle({ endEpochMs: 33_250, startEpochMs: 3_250 })
|
||||
)
|
||||
);
|
||||
assert.throws(
|
||||
() =>
|
||||
toLaunchIterationRecord(0, false, withIdle({ endEpochMs: 33_000 })),
|
||||
/idle-window-short/
|
||||
);
|
||||
assert.throws(
|
||||
() =>
|
||||
toLaunchIterationRecord(0, false, withIdle({ endEpochMs: 37_500 })),
|
||||
toLaunchIterationRecord(0, false, withIdle({ endEpochMs: 34_500 })),
|
||||
/idle-window-late/
|
||||
);
|
||||
assert.equal(
|
||||
@@ -332,7 +350,7 @@ test('refuses a launch whose settle window did not end after the first-card cuto
|
||||
const capped = toLaunchIterationRecord(
|
||||
0,
|
||||
false,
|
||||
withSettle({ epochMs: 5_650, status: 'cap' })
|
||||
withSettle({ epochMs: 3_150, status: 'cap' })
|
||||
);
|
||||
assert.equal(
|
||||
(capped.evidence['settle'] as { reason: string }).reason,
|
||||
|
||||
@@ -50,6 +50,14 @@ export const LAUNCH_JOURNEY_UNAVAILABLE_COUNTERS: Readonly<
|
||||
*/
|
||||
export const LAUNCH_JOURNEY_IDLE_LATE_TOLERANCE_MS = 1_000;
|
||||
|
||||
/**
|
||||
* The idle window opens in the settle timer's callback, but the settle point
|
||||
* is that timer's deadline. A callback that ran later than this left ticks
|
||||
* between the two outside both windows, and means the page was still busy
|
||||
* at the settle point, so the iteration is refused rather than undercounted.
|
||||
*/
|
||||
export const LAUNCH_JOURNEY_IDLE_START_TOLERANCE_MS = 100;
|
||||
|
||||
export interface LaunchJourneyMeasurement {
|
||||
readonly electronVersion: string;
|
||||
readonly gate: JourneyRendererGateState;
|
||||
@@ -230,6 +238,12 @@ function assertLaunchIdleWindow(
|
||||
if (idle.startEpochMs < settledEpochMs) {
|
||||
throw new Error('launch-journey-record-idle-before-settle');
|
||||
}
|
||||
if (
|
||||
idle.startEpochMs - settledEpochMs >
|
||||
LAUNCH_JOURNEY_IDLE_START_TOLERANCE_MS
|
||||
) {
|
||||
throw new Error('launch-journey-record-idle-start-late');
|
||||
}
|
||||
const durationMs = idle.endEpochMs - idle.startEpochMs;
|
||||
// Timers may fire up to a millisecond early after clamping.
|
||||
if (durationMs < JOURNEY_IDLE_WINDOW_MS - 1) {
|
||||
|
||||
@@ -201,9 +201,13 @@ zoneless change detection removes.
|
||||
The window opens when the settle window closes, so startup data still
|
||||
landing is not idle work, and it is timed by a renderer `setTimeout`. The
|
||||
record refuses an iteration whose window opened before the settle point or
|
||||
more than 100 ms after it (`launch-journey-record-idle-start-late`), or
|
||||
lasted less than 30 s, or more than 1 s longer
|
||||
(`launch-journey-record-idle-window-late`): a timer that late means the
|
||||
page was busy, not idle. `evidence.idle` keeps the measured `durationMs` and
|
||||
(`launch-journey-record-idle-window-late`). The window opens in the settle
|
||||
timer's callback while the settle point is that timer's deadline, so a late
|
||||
callback would leave ticks between the two outside both windows; either late
|
||||
timer means the page was busy, not idle. Locally the window opened 1-4 ms
|
||||
after the settle point. `evidence.idle` keeps the measured `durationMs` and
|
||||
`settledToIdleStartMs`. The main-process counters and the IPC capture are
|
||||
read after the window, which does not move them: they are frozen earlier.
|
||||
J2's launches skip the window (`runLaunchJourney` with `idleWindowMs: null`),
|
||||
|
||||
Reference in new issue
Block a user