From a0709642d21e23ad10fcef65624ae90b82f99181 Mon Sep 17 00:00:00 2001 From: Matthew Johnson Date: Mon, 16 Jun 2025 11:48:09 -0400 Subject: [PATCH] add thin client perf test scripts --- docs/spectator/lang/go/perf-test.md | 48 +++++++++++++++++++++++++ docs/spectator/lang/nodejs/perf-test.md | 13 +++++++ docs/spectator/lang/nodejs/usage.md | 14 ++++++++ docs/spectator/lang/py/perf-test.md | 47 ++++++++++++++++++++++++ mkdocs.yml | 3 ++ 5 files changed, 125 insertions(+) create mode 100644 docs/spectator/lang/go/perf-test.md create mode 100644 docs/spectator/lang/nodejs/perf-test.md create mode 100644 docs/spectator/lang/py/perf-test.md diff --git a/docs/spectator/lang/go/perf-test.md b/docs/spectator/lang/go/perf-test.md new file mode 100644 index 00000000..73a23c21 --- /dev/null +++ b/docs/spectator/lang/go/perf-test.md @@ -0,0 +1,48 @@ +# Performance + +## Test Script + +Test maximum single-threaded throughput for two minutes. + +```go +package main + +import ( + "fmt" + "github.com/Netflix/spectator-go/v2/spectator" + "time" +) + +func elapsed(start time.Time) float64 { + return time.Now().Sub(start).Seconds() +} + +func main() { + location := "udp" + // location := "unix" + config, _ := spectator.NewConfig(location, nil, nil) + registry, _ := spectator.NewRegistry(config) + defer registry.Close() + // add tags with some length, to simulate more real-world conditions + tags := map[string]string{"location": location, "version": "correct-horse-battery-staple"} + + maxDuration := float64(2 * 60) + start := time.Now() + + fmt.Printf("start spectator-go %s benchmark\n", location) + iteration := 1 + for elapsed(start) < maxDuration { + registry.Counter("spectator-go.publish", tags).Increment() + if iteration % 500000 == 0 { + fmt.Printf("iterations=%v elapsed=%v\n", iteration, elapsed(start)) + } + iteration++ + } + + fmt.Printf("iterations=%v rate/sec=%v\n", iteration, float64(iteration) / elapsed(start)) +} +``` + +## Results + +See [Usage > Performance](usage.md#performance). diff --git a/docs/spectator/lang/nodejs/perf-test.md b/docs/spectator/lang/nodejs/perf-test.md new file mode 100644 index 00000000..7aba38e1 --- /dev/null +++ b/docs/spectator/lang/nodejs/perf-test.md @@ -0,0 +1,13 @@ +# Performance + +## Test Script + +Test maximum single-threaded throughput for two minutes. + +```javascript +// tbd +``` + +## Results + +See [Usage > Performance](usage.md#performance). diff --git a/docs/spectator/lang/nodejs/usage.md b/docs/spectator/lang/nodejs/usage.md index 91556d33..1473e1cf 100644 --- a/docs/spectator/lang/nodejs/usage.md +++ b/docs/spectator/lang/nodejs/usage.md @@ -448,3 +448,17 @@ describe("Protocol Parser Tests", (): void => { ``` [SpectatorD]: ../../agent/usage.md + +## Performance + +On an `m5d.2xlarge` EC2 instance, with `Node.js v22.16.0` and `nflx-spectator: ^3.0.5`, we have +observed the following single-threaded performance numbers across a two-minute test window: + +* ??? requests/second over `udp` + +The benchmark incremented a single counter with two tags in a tight loop, to simulate real-world tag +usage, and the rate-per-second observed on the corresponding Atlas graph matched. The protocol line +was `74` characters in length. + +The Node.js process CPU usage was ~100% and the `spectatord` process CPU usage was ~55% on this 8 +vCPU system. diff --git a/docs/spectator/lang/py/perf-test.md b/docs/spectator/lang/py/perf-test.md new file mode 100644 index 00000000..3a51c3d9 --- /dev/null +++ b/docs/spectator/lang/py/perf-test.md @@ -0,0 +1,47 @@ +# Performance + +## Test Script + +Test maximum single-threaded throughput for two minutes. + +```python +#!/usr/bin/env python3 + +import logging +import time + +from spectator import Config, Registry + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(thread)d - %(message)s' +) + +location = "udp" +# location = "unix" +registry = Registry(Config(location)) +# add tags with some length, to simulate more real-world conditions +tags = {"location": location, "version": "correct-horse-battery-staple"} + +max_duration = 2 * 60 +start = time.perf_counter() + +def elapsed(): + return time.perf_counter() - start + +print(f"start spectator-py {location} benchmark") +iteration = 1 +while True: + registry.counter("spectator-py.publish", tags).increment() + if iteration % 500000 == 0: + print(f"iterations={iteration} elapsed={elapsed():.2f}") + if elapsed() > max_duration: + break + iteration += 1 + +print(f"iterations={iteration} rate/sec={iteration/elapsed():.2f}") +``` + +## Results + +See [Usage > Performance](usage.md#performance). diff --git a/mkdocs.yml b/mkdocs.yml index 6cb46afd..bed46ede 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -242,6 +242,7 @@ nav: - Percentile Timer: spectator/lang/go/meters/percentile-timer.md - Timer: spectator/lang/go/meters/timer.md - Migrations: spectator/lang/go/migrations.md + - Performance: spectator/lang/go/perf-test.md - Java: - Usage: spectator/lang/java/usage.md - Registry: @@ -283,6 +284,7 @@ nav: - Percentile Timer: spectator/lang/nodejs/meters/percentile-timer.md - Timer: spectator/lang/nodejs/meters/timer.md - Migrations: spectator/lang/nodejs/migrations.md + - Performance: spectator/lang/nodejs/perf-test.md - Python: - Usage: spectator/lang/py/usage.md - Meters: @@ -297,6 +299,7 @@ nav: - Percentile Timer: spectator/lang/py/meters/percentile-timer.md - Timer: spectator/lang/py/meters/timer.md - Migrations: spectator/lang/py/migrations.md + - Performance: spectator/lang/py/perf-test.md - Ruby: - Deprecated: spectator/lang/rb/deprecated.md - Patterns: