Skip to content

Commit 0b7b815

Browse files
[python_safe_point_bias] Initial commit
1 parent 1c0de05 commit 0b7b815

5 files changed

Lines changed: 81 additions & 0 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ARG BASE_IMAGE="prof-python-3.11"
2+
FROM $BASE_IMAGE
3+
4+
WORKDIR /usr/src/app
5+
6+
COPY ./scenarios/python_safe_point_bias_3.11/ /usr/src/app
7+
8+
RUN chmod 644 /usr/src/app/main.py
9+
RUN pip install --no-cache-dir -r requirements.txt
10+
11+
ENV EXECUTION_TIME_SEC=20
12+
ENV DD_TRACE_DEBUG=false
13+
ENV DD_PROFILING_MEMORY_ENABLED=false
14+
15+
CMD ddtrace-run python main.py
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# python_safe_point_bias_3.11
2+
3+
Verifies that the Python profiler correctly attributes CPU time to `slow_method` rather than to `empty_method`, which is called from `slow_method` but does no work.
4+
5+
## What the program does
6+
7+
`slow_method` performs string concatenations and then calls `empty_method`, which is a no-op. The loop runs for the full `EXECUTION_TIME_SEC` duration.
8+
9+
```python
10+
def empty_method() -> None:
11+
pass
12+
13+
def slow_method() -> None:
14+
while time() < end_time:
15+
x = "h" + "e" + "l" + "l" + "o" + ","
16+
x += "w" + "o" + "r" + "l" + "d"
17+
empty_method()
18+
```
19+
20+
## Expected behavior
21+
22+
- **cpu-time**: `slow_method` appears in ~100% of samples (inclusive), since all CPU work happens there.
23+
- **cpu-time**: `empty_method` appears in ~0% of samples; it is a no-op and should not be blamed for the CPU usage of its caller.
24+
25+
A profiler with a blame-attribution bug would incorrectly show `empty_method` consuming significant CPU time.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"test_name": "python_safe_point_bias",
3+
"stacks": [
4+
{
5+
"profile-type": "cpu-time",
6+
"stack-content": [
7+
{
8+
"regular_expression": ".*slow_method",
9+
"percent": 100,
10+
"error_margin": 5
11+
},
12+
{
13+
"regular_expression": ".*empty_method",
14+
"percent": 0,
15+
"error_margin": 5
16+
}
17+
]
18+
}
19+
],
20+
"scale_by_duration": true
21+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import os
2+
from time import time
3+
4+
5+
def empty_method() -> None:
6+
pass
7+
8+
9+
def slow_method() -> None:
10+
execution_time_sec = float(os.getenv("EXECUTION_TIME_SEC", "10"))
11+
end = time() + execution_time_sec
12+
while time() < end:
13+
x = "h" + "e" + "l" + "l" + "o" + ","
14+
x += "w" + "o" + "r" + "l" + "d"
15+
empty_method()
16+
17+
18+
if __name__ == "__main__":
19+
slow_method()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ddtrace

0 commit comments

Comments
 (0)