Skip to content

Commit b8fedc7

Browse files
committed
update benchmarking toolchain
1 parent 9ef0334 commit b8fedc7

File tree

4 files changed

+82
-11
lines changed

4 files changed

+82
-11
lines changed

bench/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
trakxbench
2+
3+
__pycache__/

bench/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ It also sets `TRAKX_CACHE` to a benchmark-only directory and deletes it between
4242
You run one script on the server and one on the client. They coordinate automatically
4343
so each goroutine count is started, benchmarked, stopped, and cleaned up.
4444

45-
Requirements: Python 3 on both machines.
45+
Requirements: Python 3 and Go on both machines (the orchestrators build binaries every run).
4646
Run these commands from the repo root so relative paths resolve.
4747

4848
### 1) On the server (runs Trakx)
@@ -58,18 +58,20 @@ Notes:
5858
- It clears the cache directory between runs (database reset).
5959
- It sets `TRAKX_CACHE` so old backups are never reused.
6060
- Do not point `--cache-dir` at any important data; it is deleted every run.
61+
- The server script builds `trakx` every run (override path with `--trakx-bin`).
6162

6263
### 2) On the client (runs trakxbench)
6364

6465
```bash
65-
bench/orchestrator_client.py --server 10.0.0.10:9077 --mode udp --goroutines 1,2,4,6,8,12,16,24,32,48,64 \\
66-
--udp 10.0.0.10:1337 --http 10.0.0.10:1337 --stats-url http://10.0.0.10:1337/stats \\
66+
bench/orchestrator_client.py --server 192.168.1.100:9077 --mode udp --goroutines 1,2,4,6,8,12,16,24,32,48,64 \
67+
--udp 192.168.1.100:1337 --http 192.168.1.100:1337 --stats-url http://192.168.1.100:1337/stats \
6768
--duration 2m --warmup 20s --concurrency 512 --scrape-ratio 0.03
6869
```
6970

7071
The client will create `bench/results/<timestamp>-udp/` with one JSON file per run.
7172

7273
If you need extra `trakxbench` flags, pass them through with `--bench-args`.
74+
The client script builds `trakxbench` every run (override path with `--bench-bin`).
7375

7476
### Manual step-through (optional)
7577

@@ -99,13 +101,13 @@ Common flags you will use:
99101
UDP example (closed-loop, max throughput):
100102

101103
```bash
102-
bench/trakxbench --mode udp --udp 10.0.0.10:1337 --duration 2m --warmup 20s --concurrency 512 --scrape-ratio 0.03 --stats http://10.0.0.10:1337/stats --out results-udp.json
104+
bench/trakxbench --mode udp --udp 192.168.1.100:1337 --duration 2m --warmup 20s --concurrency 512 --scrape-ratio 0.03 --stats http://192.168.1.100:1337/stats --out results-udp.json
103105
```
104106

105107
HTTP example (open-loop, 1000 req/s target):
106108

107109
```bash
108-
bench/trakxbench --mode http --http 10.0.0.10:1337 --rate 1000 --duration 2m --warmup 20s --concurrency 256 --scrape-ratio 0.03 --stats http://10.0.0.10:1337/stats --out results-http.json
110+
bench/trakxbench --mode http --http 192.168.1.100:1337 --rate 1000 --duration 2m --warmup 20s --concurrency 256 --scrape-ratio 0.03 --stats http://192.168.1.100:1337/stats --out results-http.json
109111
```
110112

111113
## Seeding the DB (optional but recommended)

bench/orchestrator_client.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import subprocess
88
import sys
99
import time
10+
from pathlib import Path
1011
from typing import List, Tuple, Optional
1112

1213

@@ -46,13 +47,44 @@ def run_trakxbench(cmd: List[str]) -> int:
4647
return proc.returncode
4748

4849

50+
def resolve_repo_root(value: Optional[str]) -> Path:
51+
if value:
52+
return Path(value).expanduser().resolve()
53+
return Path(__file__).resolve().parents[1]
54+
55+
56+
def has_path_sep(value: str) -> bool:
57+
return os.sep in value or (os.altsep and os.altsep in value)
58+
59+
60+
def ensure_trakxbench_binary(bin_arg: str, repo_root: Path) -> str:
61+
if not has_path_sep(bin_arg) and not bin_arg.startswith("."):
62+
bin_path = repo_root / bin_arg
63+
else:
64+
bin_path = Path(bin_arg)
65+
if not bin_path.is_absolute():
66+
bin_path = repo_root / bin_path
67+
68+
bin_path.parent.mkdir(parents=True, exist_ok=True)
69+
build = subprocess.run(
70+
["go", "build", "-o", str(bin_path), "./cmd/trakxbench"],
71+
cwd=str(repo_root),
72+
stdout=subprocess.PIPE,
73+
stderr=subprocess.STDOUT,
74+
text=True,
75+
)
76+
if build.returncode != 0:
77+
raise RuntimeError(f"failed to build trakxbench: {build.stdout.strip()}")
78+
return str(bin_path)
79+
80+
4981
def main() -> int:
5082
parser = argparse.ArgumentParser(description="Trakx benchmark client orchestrator")
5183
parser.add_argument("--server", default="127.0.0.1:9077", help="server control address")
5284
parser.add_argument("--mode", choices=["udp", "http"], required=True, help="benchmark mode")
5385
parser.add_argument("--goroutines", nargs="+", default=["1,2,4,6,8,12,16,24,32,48,64"], help="goroutine sweep list")
5486
parser.add_argument("--other-routines", type=int, default=1, help="routines for the non-tested tracker")
55-
parser.add_argument("--bench-bin", default="bench/trakxbench", help="path to trakxbench binary")
87+
parser.add_argument("--bench-bin", default="bench/bin/trakxbench", help="path to trakxbench binary (auto-built every run)")
5688
parser.add_argument("--out-dir", default="", help="output directory (default: bench/results/<timestamp>-<mode>)")
5789
parser.add_argument("--udp", default="", help="udp target host:port (default: <server>:1337)")
5890
parser.add_argument("--http", default="", help="http target host:port (default: <server>:1337)")
@@ -73,8 +105,12 @@ def main() -> int:
73105
parser.add_argument("--label", default="", help="label prefix")
74106
parser.add_argument("--pause", action="store_true", help="pause for Enter between runs")
75107
parser.add_argument("--bench-args", default="", help="extra args passed to trakxbench")
108+
parser.add_argument("--repo-root", default="", help="repo root (default: inferred)")
76109
args = parser.parse_args()
77110

111+
repo_root = resolve_repo_root(args.repo_root)
112+
args.bench_bin = ensure_trakxbench_binary(args.bench_bin, repo_root)
113+
78114
goroutines = parse_list(args.goroutines)
79115
if not goroutines:
80116
print("no goroutine values provided", file=sys.stderr)
@@ -96,7 +132,7 @@ def main() -> int:
96132

97133
if not args.out_dir:
98134
ts = time.strftime("%Y%m%d-%H%M%S")
99-
args.out_dir = f"bench/results/{ts}-{args.mode}"
135+
args.out_dir = str((repo_root / "bench" / "results" / f"{ts}-{args.mode}").resolve())
100136
os.makedirs(args.out_dir, exist_ok=True)
101137

102138
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

bench/orchestrator_server.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
import argparse
33
import json
44
import os
5-
import shutil
65
import socket
76
import subprocess
87
import sys
98
import time
9+
from pathlib import Path
1010
from typing import Optional, Tuple
1111

1212
HEARTBEAT_REQUEST = bytes([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0])
@@ -33,8 +33,33 @@ def recv_msg(fileobj) -> Optional[dict]:
3333
return json.loads(line.decode("utf-8"))
3434

3535

36-
def run_cmd(args, env=None) -> subprocess.CompletedProcess:
37-
return subprocess.run(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
36+
def run_cmd(args, env=None, cwd=None) -> subprocess.CompletedProcess:
37+
return subprocess.run(args, env=env, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
38+
39+
40+
def resolve_repo_root(value: Optional[str]) -> Path:
41+
if value:
42+
return Path(value).expanduser().resolve()
43+
return Path(__file__).resolve().parents[1]
44+
45+
46+
def has_path_sep(value: str) -> bool:
47+
return os.sep in value or (os.altsep and os.altsep in value)
48+
49+
50+
def ensure_trakx_binary(bin_arg: str, repo_root: Path) -> str:
51+
if not has_path_sep(bin_arg) and not bin_arg.startswith("."):
52+
bin_path = repo_root / bin_arg
53+
else:
54+
bin_path = Path(bin_arg)
55+
if not bin_path.is_absolute():
56+
bin_path = repo_root / bin_path
57+
58+
bin_path.parent.mkdir(parents=True, exist_ok=True)
59+
build = run_cmd(["go", "build", "-o", str(bin_path), "./cli"], env=os.environ.copy(), cwd=str(repo_root))
60+
if build.returncode != 0:
61+
raise RuntimeError(f"failed to build trakx: {build.stdout.strip()}")
62+
return str(bin_path)
3863

3964

4065
def wait_for_http(host: str, port: int, timeout: float) -> bool:
@@ -79,7 +104,7 @@ def clear_cache(cache_dir: str) -> None:
79104
def main() -> int:
80105
parser = argparse.ArgumentParser(description="Trakx benchmark server orchestrator")
81106
parser.add_argument("--listen", default="0.0.0.0:9077", help="control listen address")
82-
parser.add_argument("--trakx-bin", default="trakx", help="path to trakx binary")
107+
parser.add_argument("--trakx-bin", default="bench/bin/trakx", help="path to trakx binary (auto-built every run)")
83108
parser.add_argument("--config", default="bench/trakx.yaml", help="trakx config path")
84109
parser.add_argument("--cache-dir", default="/tmp/trakx-bench-cache", help="cache dir to reset between runs")
85110
parser.add_argument("--http-host", default="127.0.0.1", help="host for readiness check")
@@ -88,8 +113,14 @@ def main() -> int:
88113
parser.add_argument("--udp-port", type=int, default=1337, help="udp port for udp heartbeat")
89114
parser.add_argument("--ready-timeout", type=float, default=8.0, help="seconds to wait for readiness")
90115
parser.add_argument("--manual", action="store_true", help="pause for Enter before each start")
116+
parser.add_argument("--repo-root", default="", help="repo root (default: inferred)")
91117
args = parser.parse_args()
92118

119+
repo_root = resolve_repo_root(args.repo_root)
120+
args.trakx_bin = ensure_trakx_binary(args.trakx_bin, repo_root)
121+
if not os.path.isabs(args.config):
122+
args.config = str((repo_root / args.config).resolve())
123+
93124
listen_host, listen_port = parse_hostport(args.listen)
94125
env_base = os.environ.copy()
95126
env_base["TRAKX_CACHE"] = args.cache_dir

0 commit comments

Comments
 (0)