From b1e7b1af67349fd15601be75d3f6398bc20958bf Mon Sep 17 00:00:00 2001 From: r1viollet Date: Tue, 1 Aug 2023 09:07:32 +0200 Subject: [PATCH 1/2] ddprof go test case Add a test case mixing Go and C allocations --- scenarios/ddprof_go/Dockerfile | 22 +++++++ scenarios/ddprof_go/expected_profile.json | 72 +++++++++++++++++++++ scenarios/ddprof_go/main.go | 76 +++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 scenarios/ddprof_go/Dockerfile create mode 100644 scenarios/ddprof_go/expected_profile.json create mode 100644 scenarios/ddprof_go/main.go diff --git a/scenarios/ddprof_go/Dockerfile b/scenarios/ddprof_go/Dockerfile new file mode 100644 index 0000000..0ac98ee --- /dev/null +++ b/scenarios/ddprof_go/Dockerfile @@ -0,0 +1,22 @@ +# Dockerfile + +FROM golang:1.20.5 + +WORKDIR /app + +COPY ./scenarios/ddprof_go/ . + +RUN go build main.go + +# Install native profiling +ARG CACHE_DATE=2023-03-01_09:58:27 +COPY ./binaries/ /app/binaries/ +ADD ./profilers/ddprof/install_profiler.sh . +RUN ./install_profiler.sh /usr/local/bin + +ENV EXECUTION_TIME="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" +# One allocation of size 1000 every millisecond +CMD ["ddprof", "-l", "notice", "/app/main" ] diff --git a/scenarios/ddprof_go/expected_profile.json b/scenarios/ddprof_go/expected_profile.json new file mode 100644 index 0000000..1cd564e --- /dev/null +++ b/scenarios/ddprof_go/expected_profile.json @@ -0,0 +1,72 @@ +{ + "test_name": "ddprof_go", + "stacks": [ + { + "profile-type": "cpu-time", + "stack-content": [ + { + "regular_expression": ";runtime\\.goexit\\.abi0;runtime\\.main;main\\.main", + "percent": 99, + "error_margin": 5, + "labels": [ + { + "key": "process_id", + "values": [ + "1" + ] + } + ] + } + ] + }, + { + "profile-type": "cpu-samples", + "stack-content": [ + { + "regular_expression": ";runtime\\.goexit\\.abi0;runtime\\.main;main\\.main", + "percent": 99, + "error_margin": 3, + "labels": [ + { + "key": "process_id", + "values": [ + "1" + ] + } + ] + } + ] + }, + { + "profile-type": "alloc-samples", + "stack-content": [ + { + "regular_expression": ";\\[incomplete\\];;runtime\\.asmcgocall\\.abi0;cAllocateMemory", + "percent": 20, + "error_margin": 10, + "labels": [ + { + "key": "process_id", + "values": [ + "1" + ] + } + ] + }, + { + "regular_expression": ".*;x_cgo_mmap", + "percent": 80, + "error_margin": 10, + "labels": [ + { + "key": "process_id", + "values": [ + "1" + ] + } + ] + } + ] + } + ] +} diff --git a/scenarios/ddprof_go/main.go b/scenarios/ddprof_go/main.go new file mode 100644 index 0000000..77f06c0 --- /dev/null +++ b/scenarios/ddprof_go/main.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "os" + "runtime" + "strconv" + "time" +) + +/* +#include +#include + +void cAllocateMemory() { + // Allocate some memory in the C function + int size_alloc = 10000; + int* data = (int*)malloc(size_alloc * sizeof(int)); + int sum = 0; + // Use the allocated memory to avoid compiler optimizations + for (int i = 0; i < size_alloc; i++) { + data[i] = i; + } + for (int i = 0; i < size_alloc; i++) { + sum += data[i]; + } + printf("%d\n", sum); + // Free the allocated memory + free(data); +} +*/ +import "C" + +func burnCPU() { + // Simulate CPU-intensive work + for i := 0; i < 1000000000; i++ { + _ = i * i + } +} + +func allocateMemory() { + // Allocate some memory in Go + data := make([]int, 100) + + // Use the allocated memory to avoid compiler optimizations + for i := 0; i < 100; i++ { + data[i] = i + } +} + +func main() { + // Get the execution time from the environment variable + executionTimeStr := os.Getenv("EXECUTION_TIME") + executionTime, err := strconv.Atoi(executionTimeStr) + if err != nil { + fmt.Println("Error parsing EXECUTION_TIME:", err) + return + } + + // Calculate the end time based on the execution time + endTime := time.Now().Add(time.Duration(executionTime) * time.Second) + + // Run the loop until the specified duration is reached + for time.Now().Before(endTime) { + burnCPU() + allocateMemory() + C.cAllocateMemory() + time.Sleep(100 * time.Millisecond) // Sleep to simulate some delay + } + + // Print some memory stats at the end + var m runtime.MemStats + runtime.ReadMemStats(&m) + fmt.Printf("Allocated memory (bytes): %v\n", m.Alloc) + fmt.Printf("Total memory allocated (bytes): %v\n", m.TotalAlloc) +} From df91785ff9b8c0dd56e252cc15dec5b2da437c74 Mon Sep 17 00:00:00 2001 From: r1viollet Date: Tue, 1 Aug 2023 11:19:13 +0200 Subject: [PATCH 2/2] ddprof CGo test Add documentation to comment on test purpose --- scenarios/ddprof_go/Dockerfile | 8 ++++++++ scenarios/ddprof_go/README.md | 8 ++++++++ scenarios/ddprof_go/expected_profile.json | 6 +++--- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 scenarios/ddprof_go/README.md diff --git a/scenarios/ddprof_go/Dockerfile b/scenarios/ddprof_go/Dockerfile index 0ac98ee..9a1bf50 100644 --- a/scenarios/ddprof_go/Dockerfile +++ b/scenarios/ddprof_go/Dockerfile @@ -8,6 +8,14 @@ COPY ./scenarios/ddprof_go/ . RUN go build main.go + +RUN apt-get update && apt-get install -y \ + curl \ + xz-utils \ + jq \ + wget \ + && rm -rf /var/lib/apt/lists/* + # Install native profiling ARG CACHE_DATE=2023-03-01_09:58:27 COPY ./binaries/ /app/binaries/ diff --git a/scenarios/ddprof_go/README.md b/scenarios/ddprof_go/README.md new file mode 100644 index 0000000..8c3e16b --- /dev/null +++ b/scenarios/ddprof_go/README.md @@ -0,0 +1,8 @@ +# Description + +The test aims at checking that we are able to load and capture C allocations. + +# Shortcomings + +- We are not unwinding through the ASM CGo frame. +- The quantity of allocations is hard to predict considering the Go allocator reserves mmap regions. diff --git a/scenarios/ddprof_go/expected_profile.json b/scenarios/ddprof_go/expected_profile.json index 1cd564e..bf4c428 100644 --- a/scenarios/ddprof_go/expected_profile.json +++ b/scenarios/ddprof_go/expected_profile.json @@ -41,9 +41,9 @@ "profile-type": "alloc-samples", "stack-content": [ { - "regular_expression": ";\\[incomplete\\];;runtime\\.asmcgocall\\.abi0;cAllocateMemory", + "regular_expression": ".*runtime\\.asmcgocall\\.abi0;cAllocateMemory", "percent": 20, - "error_margin": 10, + "error_margin": 40, "labels": [ { "key": "process_id", @@ -56,7 +56,7 @@ { "regular_expression": ".*;x_cgo_mmap", "percent": 80, - "error_margin": 10, + "error_margin": 40, "labels": [ { "key": "process_id",