Skip to content

Commit

Permalink
Add basic PHP MicroBenchmarks (#2435)
Browse files Browse the repository at this point in the history
* Add foundation files

* (WIP) Handle environment reloads

* fix: Exclude hook after class binding

* fix: Benchmark bootstrapping & Fatal Errors

* Add PDO, Laravel, Symfony, & WordPress Benchmarks

* Add `benchmarks_opcache`

* Add trace flush & serialization benchmarks

* Send traces (if any) through sidecar

* Add SamplingRuleMatchingBench, TraceAnnotationsBench, & PHPRedisBench

* Run `benchmarks` & `benchmarks_opcache`

* Change report to `default`

* Increase RetryThreshold to 10

* Fix HookBench's hook

* Refactor & Remove Dead Code

* Add MessagePackSerializationBench

* Update README.md

* Move `phpbench/phpbench` to the `benchmarks` scenario

* Use Symfony v5.2 in SymfonyBench.php

* Add README.md

* Modify MessagePackSerializationBench.php & TraceAnnotationsBench.php to be coherent

* Consider a `profiler` and `tracer` scenario

* Compare the different hooking functions

* typo: `PHPBENCH_OPCACHE_CONFIG`

* fix: Update benchmark dependencies (Symfony & Laravel)

* bench: Empty `index.php` web requests overhead

* Add benchmark for composer telemetry parsing

---------

Co-authored-by: Bob Weinand <bob.weinand@datadoghq.com>
  • Loading branch information
PROFeNoM and bwoebi authored Jan 5, 2024
1 parent 3bd3bc6 commit 77781a4
Show file tree
Hide file tree
Showing 35 changed files with 6,897 additions and 47 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ indent_size = none
[*.{yml,yaml}]
indent_size = 2

[*.json]
indent_size = 4

[Dockerfile]
indent_size = 2

Expand Down
40 changes: 31 additions & 9 deletions .gitlab/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@ variables:
# The Dockerfile to this image is located at:
# https://github.com/DataDog/benchmarking-platform/tree/dd-trace-php

microbenchmarks:
.microbenchmarks:
stage: benchmarks
rules:
- if: $CI_PIPELINE_SOURCE != "schedule"
changes:
paths:
- profiling/**/*
compare_to: "master"
when: on_success
- when: manual
tags: ["runner:apm-k8s-tweaked-metal"]
needs: []
image:
Expand Down Expand Up @@ -41,6 +33,36 @@ microbenchmarks:
KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: dd-trace-php
FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY: "true"

benchmarks-profiler:
extends: .microbenchmarks
rules:
- if: $CI_PIPELINE_SOURCE != "schedule"
changes:
paths:
- profiling/**/*
compare_to: "master"
when: on_success
- when: manual
variables:
SCENARIO: "profiler"

benchmarks-tracer:
extends: .microbenchmarks
rules:
- if: $CI_PIPELINE_SOURCE != "schedule"
changes:
paths:
- bridge/*
- ext/**/*
- src/**/*
- zend_abstract_interface/**/*
compare_to: "master"
when: on_success
- when: manual
variables:
SCENARIO: "tracer"


download_circle_ci_release:
stage: benchmarks
rules:
Expand Down
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ Then you can run tests:
# Run C Tests (the ones in tests/ext)
$ make test_c

# Run PHP benchmarks
$ make benchmarks

# Run OPcache PHP benchmarks
$ make benchmarks_opcache

In order to run the `phpt` tests for the php extension:

```bash
Expand Down
22 changes: 22 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,10 @@ COMPOSER = $(if $(ASAN), ASAN_OPTIONS=detect_leaks=0) COMPOSER_MEMORY_LIMIT=-1 c
COMPOSER_TESTS = $(COMPOSER) --working-dir=$(TESTS_ROOT)
PHPUNIT_OPTS ?=
PHPUNIT = $(TESTS_ROOT)/vendor/bin/phpunit $(PHPUNIT_OPTS) --config=$(TESTS_ROOT)/phpunit.xml
PHPBENCH_OPTS ?=
PHPBENCH_CONFIG ?= $(TESTS_ROOT)/phpbench.json
PHPBENCH_OPCACHE_CONFIG ?= $(TESTS_ROOT)/phpbench-opcache.json
PHPBENCH = $(TESTS_ROOT)/vendor/bin/phpbench $(PHPBENCH_OPTS) run

TEST_INTEGRATIONS_70 := \
test_integrations_deferred_loading \
Expand Down Expand Up @@ -938,6 +942,11 @@ define run_tests
$(ENV_OVERRIDE) php $(TEST_EXTRA_INI) $(REQUEST_INIT_HOOK) $(PHPUNIT) $(1) --filter=$(FILTER)
endef

define run_benchmarks
$(ENV_OVERRIDE) php $(TEST_EXTRA_INI) $(REQUEST_INIT_HOOK) $(PHPBENCH) --config=$(1) --filter=$(FILTER) --report=all --output=file --output=console
endef


# use this as the first target if you want to use uncompiled files instead of the _generated_*.php compiled file.
dev:
$(Q) :
Expand Down Expand Up @@ -999,6 +1008,19 @@ test_distributed_tracing: global_test_run_dependencies
test_metrics: global_test_run_dependencies
$(call run_tests,--testsuite=metrics $(TESTS))

benchmarks_run_dependencies: global_test_run_dependencies
$(COMPOSER) --working-dir=tests/Frameworks/Symfony/Version_5_2 update
php tests/Frameworks/Symfony/Version_5_2/bin/console cache:clear --no-warmup --env=prod
$(COMPOSER) --working-dir=tests/Frameworks/Laravel/Version_8_x update
rm -f tests/.scenarios.lock/benchmarks/composer.lock
$(MAKE) test_scenario_benchmarks

benchmarks: benchmarks_run_dependencies
$(call run_benchmarks,$(PHPBENCH_CONFIG))

benchmarks_opcache: benchmarks_run_dependencies
$(call run_benchmarks,$(PHPBENCH_OPCACHE_CONFIG))

test_opentelemetry_1: global_test_run_dependencies
rm -f tests/.scenarios.lock/opentelemetry1/composer.lock
$(MAKE) test_scenario_opentelemetry1
Expand Down
25 changes: 20 additions & 5 deletions benchmark/runall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,27 @@

set -exu

cd ../profiling/
if [ "$SCENARIO" = "profiler" ]; then
# Run Profiling Benchmarks
cd ../profiling/

cargo build --release --features trigger_time_sample
cargo build --release --features trigger_time_sample

sirun benches/memory.json > "$ARTIFACTS_DIR/sirun_mem.ndjson"
sirun benches/memory.json > "$ARTIFACTS_DIR/sirun_mem.ndjson"

sed -i -e "s/crate-type.*$/crate-type = [\"rlib\"]/g" Cargo.toml
sed -i -e "s/crate-type.*$/crate-type = [\"rlib\"]/g" Cargo.toml

cargo bench --features stack_walking_tests -- --noplot
cargo bench --features stack_walking_tests -- --noplot
elif [ "$SCENARIO" = "tracer" ]; then
# Run Trace Benchmarks
cd ..
make composer_tests_update

## Non-OPCache Benchmarks
make benchmarks
cp tests/Benchmarks/reports/tracer-bench-results.csv "$ARTIFACTS_DIR"

## OPCache Benchmarks
make benchmarks_opcache
cp tests/Benchmarks/reports/tracer-bench-results-opcache.csv "$ARTIFACTS_DIR"
fi
4 changes: 4 additions & 0 deletions ext/ddtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1793,6 +1793,10 @@ PHP_FUNCTION(dd_trace_internal_fn) {
} else if (FUNCTION_NAME_MATCHES("finalize_telemetry")) {
dd_finalize_telemtry();
RETVAL_TRUE;
} else if (params_count == 1 && FUNCTION_NAME_MATCHES("detect_composer_installed_json")) {
ddog_CharSlice path = dd_zend_string_to_CharSlice(Z_STR_P(ZVAL_VARARG_PARAM(params, 0)));
ddtrace_detect_composer_installed_json(&ddtrace_sidecar, ddtrace_sidecar_instance_id, &DDTRACE_G(telemetry_queue_id), path);
RETVAL_TRUE;
} else if (FUNCTION_NAME_MATCHES("synchronous_flush")) {
uint32_t timeout = 100;
if (params_count == 1) {
Expand Down
3 changes: 1 addition & 2 deletions src/Integrations/Integrations/Logs/LogsIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use DDTrace\HookData;
use DDTrace\Integrations\Integration;
use DDTrace\Log\Logger;
use DDTrace\Util\ObjectKVStore;
use Psr\Log\NullLogger;

Expand Down Expand Up @@ -220,8 +221,6 @@ public static function getHookFn(

public function init()
{
$integration = $this;

$levelNames = [
'debug',
'info',
Expand Down
22 changes: 22 additions & 0 deletions tests/Benchmarks/API/ComposerTelemetryBench.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Benchmarks\API;

class ComposerTelemetryBench
{
/**
* @Revs(1)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
* @RetryThreshold(10.0)
*/
public function benchTelemetryParsing()
{
dd_trace_internal_fn(
"detect_composer_installed_json",
__DIR__ . "/../support/ComposerTelemetryBench/vendor/autoload.php"
);
}
}
121 changes: 121 additions & 0 deletions tests/Benchmarks/API/ContextPropagationBench.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

declare(strict_types=1);

namespace Benchmarks\API;

class ContextPropagationBench
{
public static $traceContext128Bit = [
'traceparent' => '00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01',
'tracestate' => 'rojo=00f067aa0ba902b7,dd=t.dm:-1;t.congo:t61rcWkgMzE'
];

public static $traceContext64Bit = [
'traceparent' => '00-0000000000000000sc151df7d6ee5e2d6-a3978fb9b92502a8-01',
'tracestate' => 'rojo=00f067aa0ba902b7,dd=t.dm:-1;t.congo:t61rcWkgMzE'
];

public static $headers128Bit = [
'x-datadog-trace-id' => '0af7651916cd43dd8448eb211c80319c',
'x-datadog-parent-id' => 'b7ad6b7169203331',
'x-datadog-sampling-priority' => 3,
'x-datadog-origin' => 'datadog'
];

public static $headers64Bit = [
"x-datadog-trace-id" => 42,
"x-datadog-parent-id" => 10,
"x-datadog-origin" => "datadog",
"x-datadog-sampling-priority" => 3,
];

/**
* @Revs(1)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
* @RetryThreshold(10.0)
* @BeforeMethods("resetContext")
*/
public function benchExtractTraceContext128Bit()
{
\DDTrace\consume_distributed_tracing_headers(self::$traceContext128Bit);
}

/**
* @Revs(1)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
* @RetryThreshold(10.0)
* @BeforeMethods("resetContext")
*/
public function benchExtractTraceContext64Bit()
{
\DDTrace\consume_distributed_tracing_headers(self::$traceContext64Bit);
}

/**
* @Revs(1)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
* @RetryThreshold(10.0)
* @BeforeMethods("resetContext")
*/
public function benchExtractHeaders128Bit()
{
\DDTrace\consume_distributed_tracing_headers(self::$headers128Bit);
}

/**
* @Revs(1)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
* @RetryThreshold(10.0)
* @BeforeMethods("resetContext")
*/
public function benchExtractHeaders64Bit()
{
\DDTrace\consume_distributed_tracing_headers(self::$headers64Bit);
}

/**
* @Revs(1)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
* @RetryThreshold(10.0)
* @BeforeMethods("setUp128BitContext")
*/
public function benchInject128Bit()
{
\DDTrace\generate_distributed_tracing_headers();
}

/**
* @Revs(1)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
* @RetryThreshold(10.0)
* @BeforeMethods("setUp64BitContext")
*/
public function benchInject64Bit()
{
\DDTrace\generate_distributed_tracing_headers();
}

public function setUp128BitContext()
{
$this->resetContext();
\DDTrace\consume_distributed_tracing_headers(self::$traceContext128Bit);
}

public function setUp64BitContext()
{
$this->resetContext();
\DDTrace\consume_distributed_tracing_headers(self::$traceContext64Bit);
}

public function resetContext()
{
\DDTrace\set_distributed_tracing_context("0", "0");
}
}
Loading

0 comments on commit 77781a4

Please sign in to comment.