diff --git a/benchmark/sirun/debugger/README.md b/benchmark/sirun/debugger/README.md new file mode 100644 index 00000000000..99d82104006 --- /dev/null +++ b/benchmark/sirun/debugger/README.md @@ -0,0 +1,3 @@ +# Dynamic Instrumentation Benchmarks + +Benchmark the overhead on the instrumented application of different probe configurations. diff --git a/benchmark/sirun/debugger/app.js b/benchmark/sirun/debugger/app.js new file mode 100644 index 00000000000..1f94151b434 --- /dev/null +++ b/benchmark/sirun/debugger/app.js @@ -0,0 +1,46 @@ +'use strict' + +// WARNING: CHANGES TO THIS FUNCTION WILL AFFECT THE LINE NUMBERS OF THE BREAKPOINTS + +if (process.env.DD_DYNAMIC_INSTRUMENTATION_ENABLED === 'true') { + require('./start-devtools-client') +} + +let n = 0 + +// Give the devtools client time to connect before doing work +setTimeout(doSomeWork, 250) + +function doSomeWork (arg1 = 1, arg2 = 2) { + const data = getSomeData() + data.n = n + if (++n <= 1000) { + setTimeout(doSomeWork, 1) + } +} + +// Location to put dummy breakpoint that is never hit: +// eslint-disable-next-line no-unused-vars +function dummy () { + throw new Error('This line should never execute') +} + +function getSomeData () { + const str = 'a'.repeat(1000) + const arr = Array.from({ length: 1000 }, (_, i) => i) + + const data = { + foo: 'bar', + nil: null, + undef: undefined, + bool: true + } + data.recursive = data + + for (let i = 0; i < 20; i++) { + data[`str${i}`] = str + data[`arr${i}`] = arr + } + + return data +} diff --git a/benchmark/sirun/debugger/meta.json b/benchmark/sirun/debugger/meta.json new file mode 100644 index 00000000000..cdfa0c60c1e --- /dev/null +++ b/benchmark/sirun/debugger/meta.json @@ -0,0 +1,66 @@ +{ + "name": "debugger", + "cachegrind": false, + "iterations": 20, + "instructions": true, + "variants": { + "control": { + "service": "while true; do { echo -e 'HTTP/1.1 202 Accepted\r\n\r\n'; } | nc -l 8080 > /dev/null; done", + "run": "node app.js", + "run_with_affinity": "bash -c \"taskset -c $CPU_AFFINITY node app.js\"", + "env": { + "DD_DYNAMIC_INSTRUMENTATION_ENABLED": "false" + } + }, + "enabled-but-breakpoint-not-hit": { + "service": "while true; do { echo -e 'HTTP/1.1 202 Accepted\r\n\r\n'; } | nc -l 8080 > /dev/null; done", + "run": "node app.js", + "run_with_affinity": "bash -c \"taskset -c $CPU_AFFINITY node app.js\"", + "baseline": "control", + "env": { + "DD_DYNAMIC_INSTRUMENTATION_ENABLED": "true", + "BREAKPOINT_FILE": "app.js", + "BREAKPOINT_LINE": "25" + } + }, + "line-probe-without-snapshot": { + "service": "while true; do { echo -e 'HTTP/1.1 202 Accepted\r\n\r\n'; } | nc -l 8080 > /dev/null; done", + "run": "node app.js", + "run_with_affinity": "bash -c \"taskset -c $CPU_AFFINITY node app.js\"", + "baseline": "control", + "env": { + "DD_DYNAMIC_INSTRUMENTATION_ENABLED": "true", + "BREAKPOINT_FILE": "app.js", + "BREAKPOINT_LINE": "18" + } + }, + "line-probe-with-snapshot-default": { + "service": "while true; do { echo -e 'HTTP/1.1 202 Accepted\r\n\r\n'; } | nc -l 8080 > /dev/null; done", + "run": "node app.js", + "run_with_affinity": "bash -c \"taskset -c $CPU_AFFINITY node app.js\"", + "baseline": "line-probe-without-snapshot", + "env": { + "DD_DYNAMIC_INSTRUMENTATION_ENABLED": "true", + "BREAKPOINT_FILE": "app.js", + "BREAKPOINT_LINE": "18", + "CAPTURE_SNAPSHOT": "true" + } + }, + "line-probe-with-snapshot-minimal": { + "service": "while true; do { echo -e 'HTTP/1.1 202 Accepted\r\n\r\n'; } | nc -l 8080 > /dev/null; done", + "run": "node app.js", + "run_with_affinity": "bash -c \"taskset -c $CPU_AFFINITY node app.js\"", + "baseline": "line-probe-without-snapshot", + "env": { + "DD_DYNAMIC_INSTRUMENTATION_ENABLED": "true", + "BREAKPOINT_FILE": "app.js", + "BREAKPOINT_LINE": "18", + "CAPTURE_SNAPSHOT": "true", + "MAX_REFERENCE_DEPTH": "0", + "MAX_COLLECTION_SIZE": "0", + "MAX_FIELD_COUNT": "0", + "MAX_LENGTH": "9007199254740991" + } + } + } +} diff --git a/benchmark/sirun/debugger/start-devtools-client.js b/benchmark/sirun/debugger/start-devtools-client.js new file mode 100644 index 00000000000..f743a644912 --- /dev/null +++ b/benchmark/sirun/debugger/start-devtools-client.js @@ -0,0 +1,31 @@ +'use strict' + +const Config = require('../../../packages/dd-trace/src/config') +const { start } = require('../../../packages/dd-trace/src/debugger') +const { generateProbeConfig } = require('../../../packages/dd-trace/test/debugger/devtools_client/utils') + +const breakpoint = { + file: process.env.BREAKPOINT_FILE, + line: process.env.BREAKPOINT_LINE +} +const config = new Config() +const rc = { + setProductHandler (product, cb) { + const action = 'apply' + const conf = generateProbeConfig(breakpoint, { + captureSnapshot: process.env.CAPTURE_SNAPSHOT === 'true', + capture: { + maxReferenceDepth: process.env.MAX_REFERENCE_DEPTH ? parseInt(process.env.MAX_REFERENCE_DEPTH, 10) : undefined, + maxCollectionSize: process.env.MAX_COLLECTION_SIZE ? parseInt(process.env.MAX_COLLECTION_SIZE, 10) : undefined, + maxFieldCount: process.env.MAX_FIELD_COUNT ? parseInt(process.env.MAX_FIELD_COUNT, 10) : undefined, + maxLength: process.env.MAX_LENGTH ? parseInt(process.env.MAX_LENGTH, 10) : undefined + } + }) + const id = 'id' + const ack = () => {} + + cb(action, conf, id, ack) + } +} + +start(config, rc)