File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -77,7 +77,7 @@ Both use [dd-octo-sts](https://github.com/DataDog/dd-octo-sts-action) (`dd-trace
7777**Inputs:**
7878
7979- ` dd_trace_py_commit_sha` — commit to test (required)
80- - ` test_scenarios` — regexp passed to `TEST_SCENARIOS` (dd-trace-py passes the [6 -scenario 3.14/3.15 migration gate](scenarios/python_downstream_gate/README.md); the downstream workflow default alone is `python.*`)
80+ - ` test_scenarios` — regexp passed to `TEST_SCENARIOS` (dd-trace-py passes the [8 -scenario 3.14/3.15 migration gate](scenarios/python_downstream_gate/README.md); the downstream workflow default alone is `python.*`)
8181
8282# # Creating new tests
8383
Original file line number Diff line number Diff line change 1+ ARG BASE_IMAGE="prof-python-3.14"
2+ FROM $BASE_IMAGE
3+
4+ COPY ./scenarios/python_cpu_3.14/requirements.txt /app/requirements.txt
5+ RUN pip install -r /app/requirements.txt
6+
7+ COPY ./scenarios/python_cpu_3.14/main.py /app/main.py
8+ WORKDIR /app
9+
10+ ENV EXECUTION_TIME_SEC=10
11+ ENV _DD_PROFILING_STACK_ADAPTIVE_SAMPLING_ENABLED=0
12+ ENV DD_PROFILING_ENABLED=true
13+ ENV DD_PROFILING_MEMORY_ENABLED=false
14+
15+ CMD ddtrace-run python main.py
Original file line number Diff line number Diff line change 1+ ## CPU stack profiling (3.14 baseline)
2+
3+ Validates that the Datadog Python profiler's ** stack collector** reports
4+ ` cpu-time ` samples with correct call stacks and ` thread name ` labels under a
5+ CPU-bound workload. This is the ** 3.14 baseline** half of the ` 3.14 -> 3.15 `
6+ migration pair (see ` python_cpu_3.15 ` ).
7+
8+ Reuses the workload from ` scenarios/python_cpu ` : two tight loops (` a ` and ` b ` )
9+ with a 2:1 relative CPU share. Memory profiling is disabled so the assertion
10+ targets stack samples only.
11+
12+ ## Expected profile
13+
14+ - ` cpu-time ` :
15+ - ` <module>;.*main;.*b ` ~ = 66% (` MainThread ` )
16+ - ` <module>;.*main;.*a ` ~ = 33% (` MainThread ` )
17+
18+ ` cpu-time ` is best-effort per sample, so ` error_margin ` is generous.
19+ ` scale_by_duration ` normalizes across run lengths.
20+
21+ ## Notes
22+
23+ The 3.14 scenario runs on prof-correctness ` main ` CI (PyPI ddtrace). The 3.15
24+ candidate runs only via the dd-trace-py downstream gate (` DDTRACE_INSTALL_URL ` ).
Original file line number Diff line number Diff line change 1+ {
2+ "test_name" : " python_cpu_3.14" ,
3+ "stacks" : [
4+ {
5+ "profile-type" : " cpu-time" ,
6+ "stack-content" : [
7+ {
8+ "regular_expression" : " <module>;.*main;.*b" ,
9+ "percent" : 66 ,
10+ "error_margin" : 100 ,
11+ "labels" : [
12+ {
13+ "key" : " thread name" ,
14+ "values" : [
15+ " MainThread"
16+ ]
17+ }
18+ ]
19+ },
20+ {
21+ "regular_expression" : " <module>;.*main;.*a" ,
22+ "percent" : 33 ,
23+ "error_margin" : 100 ,
24+ "labels" : [
25+ {
26+ "key" : " thread name" ,
27+ "values" : [
28+ " MainThread"
29+ ]
30+ }
31+ ]
32+ }
33+ ]
34+ }
35+ ],
36+ "scale_by_duration" : true
37+ }
Original file line number Diff line number Diff line change 1+ import os
2+ from time import time
3+
4+
5+ class CPUBurner :
6+ def __init__ (self ) -> None :
7+ self .x = 0
8+ self .i = 0
9+
10+ def a (self ) -> None :
11+ self .i = 0
12+ while self .i < 1000000 :
13+ self .x += self .i
14+ self .i += 1
15+
16+ def b (self ) -> None :
17+ self .i = 0
18+ while self .i < 2000000 :
19+ self .x += self .i
20+ self .i += 1
21+
22+ def main (self ) -> None :
23+ execution_time_sec = float (os .getenv ("EXECUTION_TIME_SEC" , "10" ))
24+ end = time () + execution_time_sec
25+ while time () < end :
26+ self .a ()
27+ self .b ()
28+
29+
30+ CPUBurner ().main ()
Original file line number Diff line number Diff line change 1+ ddtrace
Original file line number Diff line number Diff line change 1+ ARG BASE_IMAGE="prof-python-3.15"
2+ FROM $BASE_IMAGE
3+
4+ # ddtrace is pre-installed in the base image when DDTRACE_INSTALL_URL is set
5+ # (dd-trace-py downstream CI). Do not pip-install here — PyPI wheels may not
6+ # exist for 3.15 yet.
7+
8+ COPY ./scenarios/python_cpu_3.15/main.py /app/main.py
9+ WORKDIR /app
10+
11+ ENV EXECUTION_TIME_SEC=10
12+ ENV _DD_PROFILING_STACK_ADAPTIVE_SAMPLING_ENABLED=0
13+ ENV DD_PROFILING_ENABLED=true
14+ ENV DD_PROFILING_MEMORY_ENABLED=false
15+
16+ CMD ddtrace-run python main.py
Original file line number Diff line number Diff line change 1+ ## CPU stack profiling (3.15 candidate)
2+
3+ Validates that the Datadog Python profiler's ** stack collector** reports
4+ ` cpu-time ` samples with correct call stacks and ` thread name ` labels under a
5+ CPU-bound workload. This is the ** 3.15 candidate** half of the ` 3.14 -> 3.15 `
6+ migration pair (see ` python_cpu_3.14 ` ).
7+
8+ Reuses the workload from ` scenarios/python_cpu ` : two tight loops (` a ` and ` b ` )
9+ with a 2:1 relative CPU share. Memory profiling is disabled so the assertion
10+ targets stack samples only.
11+
12+ ## Expected profile
13+
14+ - ` cpu-time ` :
15+ - ` <module>;.*main;.*b ` ~ = 66% (` MainThread ` )
16+ - ` <module>;.*main;.*a ` ~ = 33% (` MainThread ` )
17+
18+ ` cpu-time ` is best-effort per sample, so ` error_margin ` is generous.
19+ ` scale_by_duration ` normalizes across run lengths.
20+
21+ ## Notes
22+
23+ This scenario is wheel-only: PyPI ddtrace wheels may not exist for 3.15 yet, so
24+ it is excluded from prof-correctness ` main ` CI and runs via the dd-trace-py
25+ downstream gate (` DDTRACE_INSTALL_URL ` ).
Original file line number Diff line number Diff line change 1+ {
2+ "test_name" : " python_cpu_3.15" ,
3+ "stacks" : [
4+ {
5+ "profile-type" : " cpu-time" ,
6+ "stack-content" : [
7+ {
8+ "regular_expression" : " <module>;.*main;.*b" ,
9+ "percent" : 66 ,
10+ "error_margin" : 100 ,
11+ "labels" : [
12+ {
13+ "key" : " thread name" ,
14+ "values" : [
15+ " MainThread"
16+ ]
17+ }
18+ ]
19+ },
20+ {
21+ "regular_expression" : " <module>;.*main;.*a" ,
22+ "percent" : 33 ,
23+ "error_margin" : 100 ,
24+ "labels" : [
25+ {
26+ "key" : " thread name" ,
27+ "values" : [
28+ " MainThread"
29+ ]
30+ }
31+ ]
32+ }
33+ ]
34+ }
35+ ],
36+ "scale_by_duration" : true
37+ }
Original file line number Diff line number Diff line change 1+ import os
2+ from time import time
3+
4+
5+ class CPUBurner :
6+ def __init__ (self ) -> None :
7+ self .x = 0
8+ self .i = 0
9+
10+ def a (self ) -> None :
11+ self .i = 0
12+ while self .i < 1000000 :
13+ self .x += self .i
14+ self .i += 1
15+
16+ def b (self ) -> None :
17+ self .i = 0
18+ while self .i < 2000000 :
19+ self .x += self .i
20+ self .i += 1
21+
22+ def main (self ) -> None :
23+ execution_time_sec = float (os .getenv ("EXECUTION_TIME_SEC" , "10" ))
24+ end = time () + execution_time_sec
25+ while time () < end :
26+ self .a ()
27+ self .b ()
28+
29+
30+ CPUBurner ().main ()
You can’t perform that action at this time.
0 commit comments