Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python CPU test - basic scenario #4

Merged
merged 3 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ find the pprof files.
Create a test scenario and prefix the folders with something relevant like `php`, `ddprof`, `go`...
The dockerfile specifies how to install the profiler and run the test app.
The dockerfile needs to follow rules
- set variable `EXECUTION_TIME` (which defines how long the tests runs for)
- set variable `EXECUTION_TIME_SEC` (which defines how long the tests runs for)
- output pprof data to the `/app/data/` folder
The /app/data mirrors the data folder in this repository.
```
# Define OS / Install App...
# Install profiler...
# Run things
ENV EXECUTION_TIME="60"
ENV EXECUTION_TIME_SEC="60"
# Default is that test data is dropped in the data folder
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
CMD ["ddprof", "-l", "notice", "/app/build/some_app" ]
Expand Down
6 changes: 3 additions & 3 deletions correctness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func buildTestApp(t *testing.T, config DockerTestConfig) string {
return string("test-app")
}

// docker run -v ${PWD}/data:/app/data:rw -e EXECUTION_TIME=60 -u $(id -u ${USER}):$(id -g ${USER}) --security-opt seccomp=unconfined test-app:latest
// docker run -v ${PWD}/data:/app/data:rw -e EXECUTION_TIME_SEC=60 -u $(id -u ${USER}):$(id -g ${USER}) --security-opt seccomp=unconfined test-app:latest

func runTestApp(t *testing.T, dockerTag string, folder string) string {
currentPath, err := os.Getwd()
Expand All @@ -135,7 +135,7 @@ func runTestApp(t *testing.T, dockerTag string, folder string) string {
t.Log(strings.Join(cmdSlice, " "))
args := []string{"run", "-v", mountOption, "-u", userOption, "--security-opt", "seccomp=unconfined"}
if DURATION_SET {
args = append(args, "-e", "EXECUTION_TIME="+fmt.Sprint(RUN_SECS))
args = append(args, "-e", "EXECUTION_TIME_SEC="+fmt.Sprint(RUN_SECS))
}
if NETWORK_HOST {
args = append(args, "--network=host")
Expand Down Expand Up @@ -180,7 +180,7 @@ func testScenarios(t *testing.T, scenarioRegexp string) {

var (
expectedJson = flag.String("expectedJson", "default.json", "Path to the expected JSON file")
pprofPath = flag.String("pprofPath", "./", "Path to the directory with the pprof")
pprofPath = flag.String("pprofPath", "./", "Path to the directory with the pprof")
)

func TestAnalyze(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion scenarios/broken_graal_vm/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ RUN ./install_profiler.sh /usr/local/bin

ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_NATIVE_LOG_MODE="/app/data/ddprof_log"
# If upload period is > EXECUTION_TIME, it can cause issues when shutting down containers
# If upload period is > EXECUTION_TIME_SEC, it can cause issues when shutting down containers
ENV DD_PROFILING_UPLOAD_PERIOD="10"

CMD ddprof -l notice /app/DummyApp 11
2 changes: 1 addition & 1 deletion scenarios/ddprof_allocations/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ COPY ./binaries/ /app/binaries/
ADD ./profilers/ddprof/install_profiler.sh .
RUN ./install_profiler.sh /usr/local/bin

ENV EXECUTION_TIME="11"
ENV EXECUTION_TIME_SEC="11"
# Default is that test data is dropped in the data folder
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_UPLOAD_PERIOD="10"
Expand Down
2 changes: 1 addition & 1 deletion scenarios/ddprof_allocations/simple_malloc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ int main(int argc, char *argv[]) {
app.add_option<std::chrono::seconds, int64_t>(
"--timeout", opts.timeout_duration, "Timeout after N seconds")
->default_val(0)
->envname("EXECUTION_TIME")
->envname("EXECUTION_TIME_SEC")
->check(CLI::NonNegativeNumber);
app.add_option<std::chrono::microseconds, int64_t>(
"--spin", opts.spin_duration_per_loop,
Expand Down
4 changes: 2 additions & 2 deletions scenarios/ddprof_clang_pie/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ FROM base AS final
ADD ./profilers/ddprof/install_profiler.sh .
RUN ./install_profiler.sh /usr/local/bin

ENV EXECUTION_TIME="12"
ENV EXECUTION_TIME_SEC="12"
# Default is that test data is dropped in the data folder
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_NATIVE_LOG_MODE="/app/data/ddprof_log"
# If upload period is > EXECUTION_TIME, it can cause issues when shutting down containers
# If upload period is > EXECUTION_TIME_SEC, it can cause issues when shutting down containers
ENV DD_PROFILING_UPLOAD_PERIOD="10"
CMD ["ddprof", "-l", "notice", "/app/build/clang_pie" ]
2 changes: 1 addition & 1 deletion scenarios/ddprof_clang_pie/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void b() {

int main(int argc, char *argv[]) {
int test_duration = 60;
const char *exec_time_env = getenv("EXECUTION_TIME");
const char *exec_time_env = getenv("EXECUTION_TIME_SEC");
if (exec_time_env) {
test_duration = atoi(exec_time_env);
if (test_duration == 0) {
Expand Down
4 changes: 2 additions & 2 deletions scenarios/ddprof_julia/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ARG CACHE_DATE=2023-03-01_09:58:27
ADD ./profilers/ddprof/install_profiler.sh .
RUN ./install_profiler.sh /usr/local/bin

ENV EXECUTION_TIME="11"
ENV EXECUTION_TIME_SEC="11"
# Default is that test data is dropped in the data folder
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_UPLOAD_PERIOD="10"
Expand All @@ -33,7 +33,7 @@ ENV ENABLE_JITPROFILING=1
# The rpath is defined by the caller of dlopen. Intercepting the call changes
# who is calling dlopen. This is not easy to fix, so I'm adding the path to Julia libs
# Debug command:
# ENABLE_JITPROFILING=1 LD_LIBRARY_PATH=~/dd/scripts/julia-1.8.5/lib/julia/ EXECUTION_TIME=30 ddprof -l notice
# ENABLE_JITPROFILING=1 LD_LIBRARY_PATH=~/dd/scripts/julia-1.8.5/lib/julia/ EXECUTION_TIME_SEC=30 ddprof -l notice
# --show_sample julia scenarios/ddprof_julia/main.jl
ENV LD_LIBRARY_PATH="/usr/local/julia/lib:${LD_LIBRARY_PATH}"
RUN mkdir /.debug && mkdir /.debug/jit && chmod 777 /.debug/jit
Expand Down
2 changes: 1 addition & 1 deletion scenarios/ddprof_julia/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include("b.jl")


test_duration = 60
exec_time_env = ENV["EXECUTION_TIME"]
exec_time_env = ENV["EXECUTION_TIME_SEC"]
if exec_time_env != nothing
test_duration = parse(Int, exec_time_env)
if test_duration == 0
Expand Down
4 changes: 2 additions & 2 deletions scenarios/ddprof_live_heap/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ FROM base AS final
ADD ./profilers/ddprof/install_profiler.sh .
RUN ./install_profiler.sh /usr/local/bin

ENV EXECUTION_TIME="12"
ENV EXECUTION_TIME_SEC="12"
# Default is that test data is dropped in the data folder
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_NATIVE_LOG_MODE="/app/data/ddprof_log"
# If upload period is > EXECUTION_TIME, it can cause issues when shutting down containers
# If upload period is > EXECUTION_TIME_SEC, it can cause issues when shutting down containers
ENV DD_PROFILING_UPLOAD_PERIOD="10"
# ddprof -l debug -e "sALLOC period=1 mode=l" -u 30 ./test
# Force deterministic by sampling all allocations
Expand Down
2 changes: 1 addition & 1 deletion scenarios/ddprof_live_heap/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void thread_function() {

int main(int argc, char** argv) {
int test_duration = 10;
const char* exec_time_env = getenv("EXECUTION_TIME");
const char* exec_time_env = getenv("EXECUTION_TIME_SEC");
if (exec_time_env) {
test_duration = atoi(exec_time_env);
if (test_duration == 0) {
Expand Down
2 changes: 1 addition & 1 deletion scenarios/node_heap/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ COPY ./scenarios/node_heap/* ./
RUN chmod 755 /app/*
RUN npm install

ENV EXECUTION_TIME="10"
ENV EXECUTION_TIME_SEC="10"
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_EXPORTERS=file
ENV DD_PROFILING_ENABLED=1
Expand Down
2 changes: 1 addition & 1 deletion scenarios/node_heap/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ async function foo(iterCount, allocPeriodMs) {
var refs = []
const allocSize = 1024 * 1024 * 2
const allocPeriodMs = 100
const durationMs = (process.argv[2] || process.env.EXECUTION_TIME || 2) * 1000
const durationMs = (process.argv[2] || process.env.EXECUTION_TIME_SEC || 2) * 1000
const iterCount = durationMs / allocPeriodMs
setTimeout(() => foo(iterCount, allocPeriodMs), 100)
2 changes: 1 addition & 1 deletion scenarios/node_heap_oom/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ COPY ./scenarios/node_heap_oom/* ./
RUN chmod 755 /app/*
RUN npm install

ENV EXECUTION_TIME="10"
ENV EXECUTION_TIME_SEC="10"
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_EXPORTERS=file
ENV DD_PROFILING_ENABLED=1
Expand Down
2 changes: 1 addition & 1 deletion scenarios/node_heap_oom/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ async function foo(size) {
for (let i = 0; i < n; i++) { x[i] = Math.random() }
}

const durationMs = (process.argv[2] || process.env.EXECUTION_TIME || 2) * 1000
const durationMs = (process.argv[2] || process.env.EXECUTION_TIME_SEC || 2) * 1000
setTimeout(() => foo(1024 * 1024 * 50), durationMs)
2 changes: 1 addition & 1 deletion scenarios/node_wall/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ COPY ./scenarios/node_wall/* ./
RUN chmod 755 /app/*
RUN npm install

ENV EXECUTION_TIME="10"
ENV EXECUTION_TIME_SEC="10"
ENV DD_PROFILING_PPROF_PREFIX="/app/data/profiles_"
ENV DD_PROFILING_EXPORTERS=file
ENV DD_PROFILING_ENABLED=1
Expand Down
2 changes: 1 addition & 1 deletion scenarios/node_wall/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ async function foo(nsecs) {
setImmediate(work);
}

const executionTime = process.argv[2] || process.env.EXECUTION_TIME || 2
const executionTime = process.argv[2] || process.env.EXECUTION_TIME_SEC || 2
setTimeout(() => foo(executionTime), 100)
2 changes: 1 addition & 1 deletion scenarios/php_allocations/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RUN ./install_profiler.sh
COPY ./scenarios/php_allocations/main.php .
RUN chmod 644 ./main.php

ENV EXECUTION_TIME="10"
ENV EXECUTION_TIME_SEC="10"
ENV DD_PROFILING_OUTPUT_PPROF="/app/data/php.pprof"
ENV DD_PROFILING_EXPERIMENTAL_ALLOCATION_ENABLED=true
ENV DD_PROFILING_ENABLED=true
Expand Down
2 changes: 1 addition & 1 deletion scenarios/php_allocations/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function b()

function main()
{
$duration = $_ENV["EXECUTION_TIME"] ?? 10;
$duration = $_ENV["EXECUTION_TIME_SEC"] ?? 10;
$end = microtime(true) + $duration;
while (microtime(true) < $end) {
$start = microtime(true);
Expand Down
2 changes: 1 addition & 1 deletion scenarios/php_time/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RUN ./install_profiler.sh
COPY ./scenarios/php_time/main.php .
RUN chmod 644 ./main.php

ENV EXECUTION_TIME="10"
ENV EXECUTION_TIME_SEC="10"
ENV DD_PROFILING_OUTPUT_PPROF="/app/data/php.pprof"
ENV DD_PROFILING_EXPERIMENTAL_CPU_TIME_ENABLED=true
ENV DD_PROFILING_EXPERIMENTAL_ALLOCATION_ENABLED=false
Expand Down
2 changes: 1 addition & 1 deletion scenarios/php_time/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function b() {
}

function main() {
$duration = $_ENV["EXECUTION_TIME"];
$duration = $_ENV["EXECUTION_TIME_SEC"];
$end = microtime(true) + ($duration / 2);
while (microtime(true) < $end) {
a();
Expand Down
2 changes: 1 addition & 1 deletion scenarios/python_basic/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM python:3.10

ENV EXECUTION_TIME="2"
ENV EXECUTION_TIME_SEC="2"
ENV DD_PROFILING_ENABLED true
ENV DD_TRACE_ENABLED false
ENV DD_TRACE_DEBUG true
Expand Down
6 changes: 3 additions & 3 deletions scenarios/python_basic/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ def target(n):


if __name__ == "__main__":
execution_time = int(os.environ.get("EXECUTION_TIME", "2"))
EXECUTION_TIME_SEC = int(os.environ.get("EXECUTION_TIME_SEC", "2"))

t = Thread(target=target, args=(execution_time / 2,))
t = Thread(target=target, args=(EXECUTION_TIME_SEC / 2,))
t.start()

target(execution_time)
target(EXECUTION_TIME_SEC)

t.join()
2 changes: 1 addition & 1 deletion scenarios/python_basic_gevent/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM python:3.10

ENV EXECUTION_TIME="2"
ENV EXECUTION_TIME_SEC="2"
ENV DD_PROFILING_ENABLED true
ENV DD_TRACE_ENABLED false
ENV DD_TRACE_DEBUG true
Expand Down
6 changes: 3 additions & 3 deletions scenarios/python_basic_gevent/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ def target(n):


if __name__ == "__main__":
execution_time = int(os.environ.get("EXECUTION_TIME", "2"))
EXECUTION_TIME_SEC = int(os.environ.get("EXECUTION_TIME_SEC", "2"))

t = Thread(target=target, args=(execution_time / 2,))
t = Thread(target=target, args=(EXECUTION_TIME_SEC / 2,))
t.start()

target(execution_time)
target(EXECUTION_TIME_SEC)

t.join()
21 changes: 21 additions & 0 deletions scenarios/python_cpu/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Use an official Python runtime as a parent image
FROM python:3.11
r1viollet marked this conversation as resolved.
Show resolved Hide resolved

# Set the working directory in the container
WORKDIR /usr/src/app

# Copy the current directory contents into the container at /app
COPY ./scenarios/python_cpu/ /usr/src/app

RUN chmod 644 /usr/src/app/main.py
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

ENV EXECUTION_TIME_SEC=10
# Run your python script when the container launches
ENV DD_PROFILING_ENABLED true
ENV DD_TRACE_ENABLED false
ENV DD_TRACE_DEBUG false
ENV DD_PROFILING_OUTPUT_PPROF="/app/data/profiles"

CMD ddtrace-run python main.py
36 changes: 36 additions & 0 deletions scenarios/python_cpu/expected_profile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
r1viollet marked this conversation as resolved.
Show resolved Hide resolved
"test_name": "python_cpu",
"stacks": [
{
"profile-type": "cpu-time",
"stack-content": [
{
"regular_expression": "\u003cmodule\u003e;main;b",
r1viollet marked this conversation as resolved.
Show resolved Hide resolved
"percent": 66,
"error_margin": 5,
r1viollet marked this conversation as resolved.
Show resolved Hide resolved
"labels": [
{
"key": "thread name",
"values": [
"MainThread"
]
}
]
},
{
"regular_expression": "\u003cmodule\u003e;main;a",
"percent": 33,
"error_margin": 6,
"labels": [
{
"key": "thread name",
"values": [
"MainThread"
]
}
]
}
]
}
]
}
31 changes: 31 additions & 0 deletions scenarios/python_cpu/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
from time import time

x = 0
i = 0

def main():
global x, i
EXECUTION_TIME_SEC = int(os.getenv("EXECUTION_TIME_SEC", "10")) # defaults to 10 if not set
end = time() + EXECUTION_TIME_SEC
while time() < end:
a()
b()
# We add a print to prevent optimization that could turn this into a no-op program
print(x)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is needed to avoid the compiler optimizing away the writes to x?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, locals would be optimized without a usage in more recent python versions.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to add a comment explaining this.


def a():
global x, i
i = 0
while i < 1000000:
x += i
i += 1

def b():
global x, i
i = 0
while i < 2000000:
x += i
i += 1

main()
1 change: 1 addition & 0 deletions scenarios/python_cpu/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ddtrace
2 changes: 1 addition & 1 deletion scenarios/ruby_basic/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def b
end

test_duration = 50
exec_time_env = ENV['EXECUTION_TIME']
exec_time_env = ENV['EXECUTION_TIME_SEC']
if exec_time_env
test_duration = exec_time_env.to_i
if test_duration == 0
Expand Down