Skip to content

Commit

Permalink
benchmark (#486)
Browse files Browse the repository at this point in the history
* benchmark setup
some initial benchmarking tests, based loosely on the spec and with some inspiration from the python-otlp tests

* link to extensive go benchmarks for inspiration

* style

* psalm + phpstan

* remove accidental commit

* style fix

* more benchmarks

* undo accidental commit
  • Loading branch information
brettmc authored Nov 24, 2021
1 parent e0211b9 commit 278f075
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ vendor/
coverage.clover
tests/coverage
.php-cs-fixer.cache
.phpbench
!tests/coverage/html/.gitkeep

# IntelliJ IDEA
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ psalm-info:
$(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/psalm --show-info=true --threads=1
phpstan:
$(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/phpstan analyse
benchmark:
$(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/phpbench run --report=default
trace examples: FORCE
docker-compose up -d --remove-orphans
$(DC_RUN_PHP) php ./examples/AlwaysOnZipkinExample.php
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"nyholm/psr7": "^1.4",
"phan/phan": "^5.0",
"php-http/mock-client": "^1.5",
"phpbench/phpbench": "^1.2",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-mockery": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
Expand Down
6 changes: 6 additions & 0 deletions phpbench.json.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema":"./vendor/phpbench/phpbench/phpbench.schema.json",
"runner.bootstrap": "vendor/autoload.php",
"runner.path": "tests/Benchmark",
"runner.file_pattern": "*Bench.php"
}
187 changes: 187 additions & 0 deletions tests/Benchmark/OtlpBench.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\Tests\Benchmark;

use Grpc\UnaryCall;
use Mockery;
use Mockery\MockInterface;
use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Contrib\OtlpGrpc\Exporter as GrpcExporter;
use OpenTelemetry\Contrib\OtlpHttp\Exporter as HttpExporter;
use Opentelemetry\Proto\Collector\Trace\V1\TraceServiceClient;
use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SDK\Trace\Attributes;
use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler;
use OpenTelemetry\SDK\Trace\SamplerInterface;
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\StreamInterface;

/**
* TODO https://github.com/open-telemetry/opentelemetry-go/blob/051227c9edded2c772a07a4d4e60dda27c3e4b20/sdk/trace/benchmark_test.go
*/
class OtlpBench
{
private TracerInterface $tracer;
private SamplerInterface $sampler;
private ResourceInfo $resource;

public function __construct()
{
$this->sampler = new AlwaysOnSampler();
$this->resource = ResourceInfo::create(new Attributes([
'service.name' => 'A123456789',
'service.version' => '1.34567890',
'service.instance.id' => '123ab456-a123-12ab-12ab-12340a1abc12',
]));
}

public function setUpNoExporter(): void
{
$processor = new SimpleSpanProcessor();
$provider = new TracerProvider($processor, $this->sampler, $this->resource);
$this->tracer = $provider->getTracer();
}

public function setUpGrpc(): void
{
$client = $this->createMockTraceServiceClient();
$exporter = new GrpcExporter('foo:4317', true, '', '', false, 10, $client);
$processor = new SimpleSpanProcessor($exporter);
$provider = new TracerProvider($processor, $this->sampler, $this->resource);
$this->tracer = $provider->getTracer();
}

/**
* @psalm-suppress UndefinedMagicMethod
* @psalm-suppress InvalidArgument
* @psalm-suppress PossiblyUndefinedMethod
*/
public function setUpGrpcHttp(): void
{
$response = Mockery::mock(ResponseInterface::class)
->allows(['getStatusCode' => 200]);
$stream = Mockery::mock(StreamInterface::class);
$request = Mockery::mock(RequestInterface::class);
$request->allows('withBody')->andReturnSelf();
$request->allows('withHeader')->andReturnSelf();
$client = Mockery::mock(ClientInterface::class)
->allows(['sendRequest' => $response]);
$requestFactory = Mockery::mock(RequestFactoryInterface::class)
->allows(['createRequest' => $request]);
$streamFactory = Mockery::mock(StreamFactoryInterface::class)
->allows(['createStream' => $stream]);
// @phpstan-ignore-next-line
$exporter = new HttpExporter($client, $requestFactory, $streamFactory);
$processor = new SimpleSpanProcessor($exporter);
$provider = new TracerProvider($processor, $this->sampler, $this->resource);
$this->tracer = $provider->getTracer();
}

/**
* @BeforeMethods("setUpNoExporter")
* @Revs(1000)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
*/
public function benchCreateSpans(): void
{
$span = $this->tracer->spanBuilder('foo')
->setAttribute('foo', PHP_INT_MAX)
->startSpan();
$span->addEvent('my_event');
$span->end();
}

/**
* @BeforeMethods("setUpNoExporter")
* @Revs(1000)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
*/
public function benchCreateSpansWithStackTrace(): void
{
$span = $this->tracer->spanBuilder('foo')
->setAttribute('foo', PHP_INT_MAX)
->startSpan();
$span->recordException(new \Exception('foo'));
$span->end();
}

/**
* @BeforeMethods("setUpNoExporter")
* @ParamProviders("provideEventCounts")
* @Revs(1000)
* @Iterations(5)
* @OutputTimeUnit("microseconds")
*/
public function benchCreateSpansWithMultipleEvents(array $params): void
{
$span = $this->tracer->spanBuilder('foo')
->setAttribute('foo', PHP_INT_MAX)
->startSpan();
for ($i=0; $i < $params[0]; $i++) {
$span->addEvent('event-' . $i);
}
$span->end();
}

public function provideEventCounts(): \Generator
{
yield [1];
yield [4];
yield [16];
yield [256];
}

/**
* @BeforeMethods("setUpGrpc")
* @Revs(1000)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
*/
public function benchExportSpans_OltpGrpc(): void
{
$span = $this->tracer->spanBuilder('foo')
->setAttribute('foo', PHP_INT_MAX)
->startSpan();
$span->addEvent('my_event');
$span->end();
}

/**
* @BeforeMethods("setUpGrpcHttp")
* @Revs(1000)
* @Iterations(10)
* @OutputTimeUnit("microseconds")
*/
public function benchExportSpans_OtlpHttp(): void
{
$span = $this->tracer->spanBuilder('foo')
->setAttribute('foo', PHP_INT_MAX)
->startSpan();
$span->addEvent('my_event');
$span->end();
}

private function createMockTraceServiceClient()
{
// @var MockInterface&TraceServiceClient
$unaryCall = Mockery::mock(UnaryCall::class)
->allows(['wait' => [
'unused response data',
(object) ['code' => \Grpc\STATUS_OK],
]]);
$mockClient = Mockery::mock(TraceServiceClient::class)
->allows(['Export'=> $unaryCall]);

return $mockClient;
}
}

0 comments on commit 278f075

Please sign in to comment.