Class SnapshotPacing

java.lang.Object
ai.attackframework.tools.burp.utils.concurrent.SnapshotPacing

public final class SnapshotPacing extends Object
Pacing primitives for snapshot reporters that walk large per-item collections (proxy history, sitemap, websocket history) and risk dominating JVM allocation throughput.

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_ITEMS items, a brief LockSupport.parkNanos(long) sleeps for PERIODIC_YIELD_NS so 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 exceeds GC_DUTY_BACKPRESSURE_THRESHOLD, the snapshot thread sleeps for an additional GC_DUTY_BACKPRESSURE_PAUSE_MS so G1's concurrent phases can catch up before the next chunk is built. The cached observation is exposed via gcSaturated() 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

    Fields
    Modifier and Type
    Field
    Description
    static final long
    Additional sleep applied when the GC duty cycle gate trips.
    static final double
    GC duty cycle (fraction in [0, 1]) above which the snapshot is throttled.
    static final long
    Brief per-item yield duration.
    static final int
    Per-item pacing fires when the loop counter is a positive multiple of this value.
  • Method Summary

    Modifier and Type
    Method
    Description
    static long
    Cumulative wall-clock time spent inside the GC duty-cycle gate since the last reset.
    static long
    Cumulative wall-clock time spent inside the periodic per-item yield since the last reset.
    static long
    Number of pacing boundaries where the GC duty-cycle gate engaged and slept.
    static boolean
    Returns true when the most recently sampled GC duty cycle exceeds the configured threshold.
    static long
    Returns the most recently sampled GC duty cycle as integer per-mille in [0, 1000].
    static long
    Number of paceItem(int) invocations that landed on a pacing boundary.
    static long
    Total number of paceItem(int) invocations since the last counter reset.
    static void
    paceItem(int itemIndex)
    Per-item pacing hook for snapshot loops.
    static void
    Resets only the run-scoped counters (call counts, gate trips, sleep totals).
    static void
    Test seam: reset all sampler state so tests start from a clean slate.
    static void
    Test seam: simulate a duty-cycle observation without touching JMX beans.
    static String
    Returns a single key=value summary string of the run-scoped counters for use in diagnostic log lines.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • YIELD_EVERY_N_ITEMS

      public static final int YIELD_EVERY_N_ITEMS
      Per-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_NS
      Brief per-item yield duration.
      See Also:
    • GC_DUTY_BACKPRESSURE_THRESHOLD

      public static final double GC_DUTY_BACKPRESSURE_THRESHOLD
      GC 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_MS
      Additional 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 of YIELD_EVERY_N_ITEMS.
    • gcSaturated

      public static boolean gcSaturated()
      Returns true when 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 of paceItem(int) invocations since the last counter reset.
    • paceBoundaryCount

      public static long paceBoundaryCount()
      Number of paceItem(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

      public static String summaryLine(String tag)
      Returns a single key=value summary 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 *ForTests convention 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 *ForTests convention used elsewhere in the codebase; production code never invokes it.