Class SnapshotPacing
Two complementary mechanisms work together at the same boundary points and are deliberately independent of the live traffic queue depth, since synchronous bulk pushes drain the queue at least as fast as the snapshot loop fills it:
- Periodic per-item yield. Every
YIELD_EVERY_N_ITEMSitems, a briefLockSupport.parkNanos(long)sleeps forPERIODIC_YIELD_NSso the EDT, GC concurrent threads, and other background workers get scheduled. The wall-clock cost over a full snapshot is small, but it eliminates the worst stop-the-world EDT starvation cases that occur when one CPU core is pinned by the snapshot loop. - GC duty-cycle gate. At the same boundary, the JMX
GarbageCollectorMXBean.getCollectionTime()totals are sampled and the fraction of recent wall-clock time spent in GC is computed. When that fraction exceedsGC_DUTY_BACKPRESSURE_THRESHOLD, the snapshot thread sleeps for an additionalGC_DUTY_BACKPRESSURE_PAUSE_MSso G1's concurrent phases can catch up before the next chunk is built. The cached observation is exposed viagcSaturated()so chunk-level backpressure code can additionally shrink chunk targets and reduce the resident allocation footprint of the in-flight chunk list.
Sampling is bounded to the periodic boundary (a few JMX bean reads every
YIELD_EVERY_N_ITEMS items), so callers can invoke paceItem(int)
on every iteration of a tight loop without measurable overhead.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longAdditional sleep applied when the GC duty cycle gate trips.static final doubleGC duty cycle (fraction in[0, 1]) above which the snapshot is throttled.static final longBrief per-item yield duration.static final intPer-item pacing fires when the loop counter is a positive multiple of this value. -
Method Summary
Modifier and TypeMethodDescriptionstatic longCumulative wall-clock time spent inside the GC duty-cycle gate since the last reset.static longCumulative wall-clock time spent inside the periodic per-item yield since the last reset.static longNumber of pacing boundaries where the GC duty-cycle gate engaged and slept.static booleanReturnstruewhen the most recently sampled GC duty cycle exceeds the configured threshold.static longReturns the most recently sampled GC duty cycle as integer per-mille in[0, 1000].static longNumber ofpaceItem(int)invocations that landed on a pacing boundary.static longTotal number ofpaceItem(int)invocations since the last counter reset.static voidpaceItem(int itemIndex) Per-item pacing hook for snapshot loops.static voidResets only the run-scoped counters (call counts, gate trips, sleep totals).static voidTest seam: reset all sampler state so tests start from a clean slate.static voidsetCachedDutyPerMilleForTests(long perMille) Test seam: simulate a duty-cycle observation without touching JMX beans.static StringsummaryLine(String tag) Returns a singlekey=valuesummary string of the run-scoped counters for use in diagnostic log lines.
-
Field Details
-
YIELD_EVERY_N_ITEMS
public static final int YIELD_EVERY_N_ITEMSPer-item pacing fires when the loop counter is a positive multiple of this value.- See Also:
-
PERIODIC_YIELD_NS
public static final long PERIODIC_YIELD_NSBrief per-item yield duration.- See Also:
-
GC_DUTY_BACKPRESSURE_THRESHOLD
public static final double GC_DUTY_BACKPRESSURE_THRESHOLDGC duty cycle (fraction in[0, 1]) above which the snapshot is throttled.- See Also:
-
GC_DUTY_BACKPRESSURE_PAUSE_MS
public static final long GC_DUTY_BACKPRESSURE_PAUSE_MSAdditional sleep applied when the GC duty cycle gate trips.- See Also:
-
-
Method Details
-
paceItem
public static void paceItem(int itemIndex) Per-item pacing hook for snapshot loops.Call once per item processed. No-op except at every
YIELD_EVERY_N_ITEMS-th iteration, where it briefly yields and (if GC pressure is high) sleeps long enough to let concurrent collection catch up.- Parameters:
itemIndex- 0-based or 1-based loop counter; pacing fires only when the counter is a positive multiple ofYIELD_EVERY_N_ITEMS.
-
gcSaturated
public static boolean gcSaturated()Returnstruewhen the most recently sampled GC duty cycle exceeds the configured threshold.Does not re-sample the JMX beans; sampling happens inside
paceItem(int)so callers like chunk-level backpressure observe the same value the per-item gate just acted on. -
lastDutyPerMille
public static long lastDutyPerMille()Returns the most recently sampled GC duty cycle as integer per-mille in[0, 1000]. -
paceCallCount
public static long paceCallCount()Total number ofpaceItem(int)invocations since the last counter reset. -
paceBoundaryCount
public static long paceBoundaryCount()Number ofpaceItem(int)invocations that landed on a pacing boundary. -
gateTripCount
public static long gateTripCount()Number of pacing boundaries where the GC duty-cycle gate engaged and slept. -
cumulativeGateSleepMs
public static long cumulativeGateSleepMs()Cumulative wall-clock time spent inside the GC duty-cycle gate since the last reset. -
cumulativeYieldMs
public static long cumulativeYieldMs()Cumulative wall-clock time spent inside the periodic per-item yield since the last reset. -
summaryLine
Returns a singlekey=valuesummary string of the run-scoped counters for use in diagnostic log lines. Pure read; does not reset state.- Parameters:
tag- short identifier of the calling snapshot (e.g."ProxyHistory").
-
resetCountersForSnapshot
public static void resetCountersForSnapshot()Resets only the run-scoped counters (call counts, gate trips, sleep totals).Leaves the rolling GC-duty sampler state intact so the first
paceItem(int)call after reset still produces a meaningful duty-cycle reading from the prior wall-clock observation. -
setCachedDutyPerMilleForTests
public static void setCachedDutyPerMilleForTests(long perMille) Test seam: simulate a duty-cycle observation without touching JMX beans.Sets the cached duty so
gcSaturated()reflects the supplied value on the next call. Public to match the*ForTestsconvention used elsewhere in the codebase; production code never invokes it.- Parameters:
perMille- observation in[0, 1000]; clamped if out of range
-
resetForTests
public static void resetForTests()Test seam: reset all sampler state so tests start from a clean slate.Public to match the
*ForTestsconvention used elsewhere in the codebase; production code never invokes it.
-