From ac634fc71f60375248a887557a77712120689f34 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Thu, 18 Jun 2026 11:41:06 +0200 Subject: [PATCH] fix(chaos): rate-limit tight-loop antagonists to prevent long-run OOM Co-Authored-By: Claude Sonnet 4.6 --- .../profiler/chaos/ClassLoaderChurnAntagonist.java | 8 ++++++++ .../profiler/chaos/HiddenClassChurnAntagonist.java | 8 ++++++++ .../profiler/chaos/WeakRefWaveAntagonist.java | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/ClassLoaderChurnAntagonist.java b/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/ClassLoaderChurnAntagonist.java index 283e9237b..d3f9bd569 100644 --- a/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/ClassLoaderChurnAntagonist.java +++ b/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/ClassLoaderChurnAntagonist.java @@ -77,6 +77,14 @@ private void loop() { // transient; JVM crash is the signal we watch for } // loader + klass go out of scope here. + // Pace class loading so old-gen GC can reclaim ClassLoader + // instances before they accumulate across a long run. + try { + Thread.sleep(1L); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } } } diff --git a/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/HiddenClassChurnAntagonist.java b/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/HiddenClassChurnAntagonist.java index d63729c18..d496b4060 100644 --- a/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/HiddenClassChurnAntagonist.java +++ b/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/HiddenClassChurnAntagonist.java @@ -102,6 +102,14 @@ private void loop() { } catch (Throwable t) { // transient; JVM crash is the signal we watch for } + // Pace hidden-class generation so the GC can evict unloaded + // classes before they accumulate across a long run. + try { + Thread.sleep(1L); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } } } diff --git a/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/WeakRefWaveAntagonist.java b/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/WeakRefWaveAntagonist.java index cc0d5158f..c58aa8915 100644 --- a/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/WeakRefWaveAntagonist.java +++ b/ddprof-stresstest/src/chaos/java/com/datadoghq/profiler/chaos/WeakRefWaveAntagonist.java @@ -31,6 +31,7 @@ public final class WeakRefWaveAntagonist implements Antagonist { private static final int WAVE_SIZE = 10_000; private static final int[] OBJECT_SIZES = {64, 256, 1_024, 4_096}; + private static final long INTER_WAVE_MS = 200L; private volatile boolean running; private Thread waveDriver; @@ -100,6 +101,15 @@ private void waveLoop() { // Replace shared reference; weakRefs goes out of scope currentWave = new ArrayList>(); + + // Pause between waves so concurrent GC can reclaim without being + // overwhelmed by back-to-back System.gc() calls. + try { + Thread.sleep(INTER_WAVE_MS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } } }