Skip to content

Commit 189ba80

Browse files
[python_greenlet] Initial commit
1 parent 35c644a commit 189ba80

File tree

4 files changed

+194
-0
lines changed

4 files changed

+194
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
ARG BASE_IMAGE="prof-python-3.11"
2+
FROM $BASE_IMAGE
3+
4+
# Copy the Python target into the container
5+
COPY ./scenarios/python_greenlet_3.11/requirements.txt /app/
6+
RUN chmod 644 /app/*
7+
8+
# Set the working directory to the location of the program
9+
WORKDIR /app
10+
11+
RUN pip install -r requirements.txt
12+
13+
COPY ./scenarios/python_greenlet_3.11/main.py /app/
14+
15+
ENV DD_PROFILING_ENABLED=true
16+
ENV DD_TRACE_ENABLED=false
17+
ENV DD_TRACE_DEBUG=false
18+
ENV DD_PROFILING_OUTPUT_PPROF="/app/data/profiles"
19+
ENV EXECUTION_TIME_SEC="4"
20+
21+
# Run the program when the container starts
22+
CMD ddtrace-run python main.py
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{
2+
"test_name": "python_greenlet_3.11",
3+
"scale_by_duration": false,
4+
"pprof-regex": "",
5+
"stacks": [
6+
{
7+
"profile-type": "wall-time",
8+
"pprof-regex": "",
9+
"stack-content": [
10+
{
11+
"regular_expression": ".*work_a.*",
12+
"percent": 50,
13+
"error_margin": 10,
14+
"labels": [
15+
{
16+
"key": "thread name",
17+
"values": [
18+
"MainThread"
19+
]
20+
}
21+
]
22+
}
23+
]
24+
},
25+
{
26+
"profile-type": "wall-time",
27+
"pprof-regex": "",
28+
"stack-content": [
29+
{
30+
"regular_expression": ".*work_b.*",
31+
"percent": 50,
32+
"error_margin": 10,
33+
"labels": [
34+
{
35+
"key": "thread name",
36+
"values": [
37+
"MainThread"
38+
]
39+
}
40+
]
41+
}
42+
]
43+
},
44+
{
45+
"profile-type": "wall-time",
46+
"pprof-regex": "",
47+
"stack-content": [
48+
{
49+
"regular_expression": ".*work_dependency.*",
50+
"percent": 25,
51+
"error_margin": 10,
52+
"labels": [
53+
{
54+
"key": "thread name",
55+
"values": [
56+
"MainThread"
57+
]
58+
}
59+
]
60+
}
61+
]
62+
},
63+
{
64+
"profile-type": "wall-time",
65+
"pprof-regex": "",
66+
"stack-content": [
67+
{
68+
"regular_expression": ".*work_a;.*work_dependency.*",
69+
"percent": 13,
70+
"error_margin": 10,
71+
"labels": [
72+
{
73+
"key": "thread name",
74+
"values": [
75+
"MainThread"
76+
]
77+
}
78+
]
79+
}
80+
]
81+
},
82+
{
83+
"profile-type": "wall-time",
84+
"pprof-regex": "",
85+
"stack-content": [
86+
{
87+
"regular_expression": ".*work_b;.*work_dependency.*",
88+
"percent": 13,
89+
"error_margin": 10,
90+
"labels": [
91+
{
92+
"key": "thread name",
93+
"values": [
94+
"MainThread"
95+
]
96+
}
97+
]
98+
}
99+
]
100+
}
101+
]
102+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""Test scenario for greenlet profiling."""
2+
3+
import os
4+
import time
5+
6+
import greenlet
7+
8+
9+
class GreenletBurner:
10+
def __init__(self) -> None:
11+
self.greenlet_a = greenlet.greenlet(self.work_a)
12+
self.greenlet_b = greenlet.greenlet(self.work_b)
13+
14+
self.total_count_a = 0
15+
self.total_count_b = 0
16+
17+
def work_dependency(self, count:int)->tuple[bool, int]:
18+
count += 1
19+
if count % 10000 == 0:
20+
return True, count
21+
22+
return False, count
23+
24+
def work_a(self) -> None:
25+
"""Perform work in greenlet A."""
26+
end_time = time.monotonic() + 0.1
27+
count = 0
28+
while time.monotonic() < end_time:
29+
has_dependency, count = self.work_dependency(count)
30+
if has_dependency:
31+
self.greenlet_b.switch()
32+
33+
self.total_count_a += 1
34+
35+
def work_b(self) -> None:
36+
"""Perform work in greenlet B."""
37+
end_time = time.monotonic() + 0.1
38+
count = 0
39+
while time.monotonic() < end_time:
40+
has_dependency, count = self.work_dependency(count)
41+
if has_dependency:
42+
self.greenlet_a.switch()
43+
44+
self.total_count_b += 1
45+
46+
def work(self) -> None:
47+
self.greenlet_a.switch()
48+
self.greenlet_b.switch()
49+
50+
self.greenlet_a = greenlet.greenlet(self.work_a)
51+
self.greenlet_b = greenlet.greenlet(self.work_b)
52+
53+
def main()->None:
54+
execution_time_sec = int(os.environ.get("EXECUTION_TIME_SEC", "10"))
55+
56+
greenlet_burner = GreenletBurner()
57+
58+
# Run for specified duration
59+
end_time = time.monotonic() + execution_time_sec
60+
61+
while time.monotonic() < end_time:
62+
# Start switching between greenlets
63+
greenlet_burner.work()
64+
65+
print(f"Completed execution for {execution_time_sec} seconds")
66+
67+
if __name__ == "__main__":
68+
main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ddtrace
2+
greenlet

0 commit comments

Comments
 (0)