Skip to content

Commit 6d392a7

Browse files
authored
test: coarsen ASan sampling rate/workload to stop nightly heap OOMs (#653)
1 parent a4841f3 commit 6d392a7

4 files changed

Lines changed: 30 additions & 10 deletions

File tree

ddprof-test/src/test/java/com/datadoghq/profiler/cpu/CTimerSamplerTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ protected void after() throws Exception {
7272

7373
@Override
7474
protected String getProfilerCommand() {
75-
return "cpu=100us,event=ctimer";
75+
// cpu=100us signal-based sampling is much more expensive under ASAN (the signal
76+
// handler itself is ASAN-instrumented), which can inflate the sample count and,
77+
// via the per-sample stack-trace materialization above, the test heap. Sample
78+
// coarser under ASAN.
79+
return isAsan() ? "cpu=1ms,event=ctimer" : "cpu=100us,event=ctimer";
7680
}
7781
}

ddprof-test/src/test/java/com/datadoghq/profiler/cpu/LightweightContextCpuTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ protected void after() throws Exception {
7979

8080
@Override
8181
protected String getProfilerCommand() {
82-
return "cpu=100us,lightweight=yes";
82+
// cpu=100us signal-based sampling is much more expensive under ASAN (the signal
83+
// handler itself is ASAN-instrumented), which can inflate the sample count and,
84+
// via the per-sample accessor calls above, the test heap. Sample coarser under ASAN.
85+
return isAsan() ? "cpu=1ms,lightweight=yes" : "cpu=100us,lightweight=yes";
8386
}
8487
}

ddprof-test/src/test/java/com/datadoghq/profiler/metadata/MetadataNormalisationTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,18 @@ public void test() throws Exception {
2727
Method arrayListAdd = ArrayList.class.getDeclaredMethod("add", Object.class);
2828
Constructor<?> linkedListConstructor = LinkedList.class.getConstructor();
2929
Method linkedListAdd = LinkedList.class.getDeclaredMethod("add", Object.class);
30-
// need to invoke enough times to result in generation of accessors and to record some cpu time
30+
// need to invoke enough times to result in generation of accessors and to record some cpu time.
31+
// Under ASAN, cpu=100us sampling combined with this fixed iteration count produces a much
32+
// larger sample set (stack-trace signal handling is slower under ASAN), and every sample's
33+
// stack trace is materialized below, so reduce the iteration count to bound the sample count.
34+
int iterations = isAsan() ? 10_000 : 100_000;
3135
int count = 0;
32-
for (int i = 0; i < 100_000; i++) {
36+
for (int i = 0; i < iterations; i++) {
3337
Object list = arrayListConstructor.newInstance();
3438
arrayListAdd.invoke(list, "element");
3539
count += ((List<?>) list).size();
3640
}
37-
for (int i = 0; i < 100_000; i++) {
41+
for (int i = 0; i < iterations; i++) {
3842
Object list = linkedListConstructor.newInstance();
3943
linkedListAdd.invoke(list, "element");
4044
count += ((List<?>) list).size();
@@ -63,6 +67,6 @@ public void test() throws Exception {
6367

6468
@Override
6569
protected String getProfilerCommand() {
66-
return "cpu=100us";
70+
return isAsan() ? "cpu=1ms" : "cpu=100us";
6771
}
6872
}

ddprof-test/src/test/java/com/datadoghq/profiler/wallclock/MegamorphicCallTest.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@
2020
public class MegamorphicCallTest extends AbstractProfilerTest {
2121
@Override
2222
protected String getProfilerCommand() {
23-
return "wall=100us";
23+
// wall=100us over the fixed workload below is ~10k samples/s. Under ASAN each
24+
// invocation is much slower, so the same fixed-rate sampling over a much longer
25+
// wall-clock duration produces hundreds of thousands of samples, and stack-trace
26+
// stringification of all of them (below) OOMs the test-runner heap. Sample 10x
27+
// coarser under ASAN, combined with a smaller workload, to bound the sample count.
28+
return isAsan() ? "wall=1ms" : "wall=100us";
2429
}
2530

2631
private static int calculation() {
@@ -60,9 +65,9 @@ public int calculate() {
6065
}
6166
}
6267

63-
private int profiledWork(Calculator... calculators) {
68+
private int profiledWork(int iterations, Calculator... calculators) {
6469
int result = 0;
65-
for (int i = 0; i < 1_000_000; i++) {
70+
for (int i = 0; i < iterations; i++) {
6671
for (Calculator calculator : calculators) {
6772
result += calculator.calculate();
6873
}
@@ -74,7 +79,11 @@ private int profiledWork(Calculator... calculators) {
7479
public void testITableStubs() {
7580
Assumptions.assumeFalse(Platform.isZing() || Platform.isJ9());
7681
registerCurrentThreadForWallClockProfiling();
77-
int result = profiledWork(new Calculator1(), new Calculator2(), new Calculator3());
82+
// Reduce workload under ASAN: combined with the coarser wall rate above, this
83+
// bounds the number of samples (and thus the stack-trace strings materialized
84+
// below) regardless of how much ASAN slows down each invocation.
85+
int iterations = isAsan() ? 100_000 : 1_000_000;
86+
int result = profiledWork(iterations, new Calculator1(), new Calculator2(), new Calculator3());
7887
System.err.println(result);
7988
stopProfiler();
8089
IItemCollection events = verifyEvents("datadog.MethodSample");

0 commit comments

Comments
 (0)