mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-13 08:13:11 +00:00
Add P2P split-container netem stress fixture
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
FROM node:24-slim
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends ca-certificates curl unzip python3 make g++ \
|
||||
&& apt-get install -y --no-install-recommends ca-certificates curl unzip python3 make g++ iproute2 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV DENO_INSTALL=/usr/local
|
||||
@@ -25,6 +25,7 @@ WORKDIR /workspace/src/apps/cli/testdeno
|
||||
RUN deno cache --lock=deno.lock \
|
||||
bench-network-cases.ts \
|
||||
bench-latency-sweep.ts \
|
||||
bench-p2p-split-node.ts \
|
||||
bench-p2p.ts \
|
||||
bench-couchdb.ts
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ is executed in an actual tethered/VPN environment.
|
||||
The primary local comparison is between a remote-database path and a direct P2P
|
||||
path:
|
||||
|
||||
| Case | Data path | What is measured | What is not measured |
|
||||
| --- | --- | --- | --- |
|
||||
| `couchdb-baseline` | Device A -> CouchDB -> Device B | Two one-shot CLI synchronisation commands through a local HTTP latency proxy | Real WAN jitter, packet loss, bandwidth limits, VPN encapsulation, and server contention |
|
||||
| Case | Data path | What is measured | What is not measured |
|
||||
| ------------------ | ------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
|
||||
| `couchdb-baseline` | Device A -> CouchDB -> Device B | Two one-shot CLI synchronisation commands through a local HTTP latency proxy | Real WAN jitter, packet loss, bandwidth limits, VPN encapsulation, and server contention |
|
||||
| `p2p-direct-local` | Device A -> Device B after Nostr signalling | One CLI P2P synchronisation command over WebRTC DataChannel with TURN disabled | Public relay operation, mobile carrier behaviour, TURN relay throughput, and first-peer discovery latency |
|
||||
|
||||
Use the CouchDB result as the remote-store baseline and the P2P result as the
|
||||
@@ -138,6 +138,61 @@ NETEM_MTU=1380 \
|
||||
docker compose -f test/bench-network/compose.yml --profile netem run --rm netem-smoke
|
||||
```
|
||||
|
||||
## Split-container P2P emulation
|
||||
|
||||
The optional `p2p-split` profile runs the P2P host and client in separate
|
||||
Compose services. Each service can apply `tc netem` to its own egress interface
|
||||
and the client result records the selected WebRTC ICE candidate pair.
|
||||
|
||||
```bash
|
||||
BENCH_MD_FILE_COUNT=2 \
|
||||
BENCH_BIN_FILE_COUNT=1 \
|
||||
BENCH_PEERS_TIMEOUT=10 \
|
||||
BENCH_SPLIT_RUN_ID="$(date -u +%Y%m%d%H%M%S)" \
|
||||
docker compose -f test/bench-network/compose.yml --profile p2p-split up \
|
||||
--abort-on-container-exit --exit-code-from p2p-split-client \
|
||||
p2p-split-host p2p-split-client
|
||||
```
|
||||
|
||||
By default this uses the `home-wifi` profile (`20 ms` delay, `5 ms` jitter,
|
||||
`0.1%` loss, `100 Mbit`, and `1500` MTU) on both P2P containers. Override the
|
||||
same `NETEM_*` variables used by the TCP shim to model a stricter profile.
|
||||
|
||||
```bash
|
||||
BENCH_MD_FILE_COUNT=100 \
|
||||
BENCH_MD_MIN_SIZE_BYTES=512 \
|
||||
BENCH_MD_MAX_SIZE_BYTES=2048 \
|
||||
BENCH_BIN_FILE_COUNT=25 \
|
||||
BENCH_BIN_SIZE_BYTES=8192 \
|
||||
BENCH_PEERS_TIMEOUT=60 \
|
||||
BENCH_SYNC_TIMEOUT=420 \
|
||||
BENCH_SPLIT_RUN_ID="$(date -u +%Y%m%d%H%M%S)" \
|
||||
BENCH_NETWORK_PROFILE=tethering-vpn \
|
||||
NETEM_PROFILE=tethering-vpn \
|
||||
NETEM_DELAY_MS=140 \
|
||||
NETEM_JITTER_MS=50 \
|
||||
NETEM_LOSS_PERCENT=1.0 \
|
||||
NETEM_BANDWIDTH_MBIT=10 \
|
||||
NETEM_MTU=1380 \
|
||||
docker compose -f test/bench-network/compose.yml --profile p2p-split up \
|
||||
--abort-on-container-exit --exit-code-from p2p-split-client \
|
||||
p2p-split-host p2p-split-client
|
||||
```
|
||||
|
||||
This is a Linux-only manual benchmark fixture, not a required pull-request CI
|
||||
job. It shapes each P2P container's egress path, including signalling traffic,
|
||||
and should be reported separately from the CouchDB TCP-shim measurements. The
|
||||
result JSON includes `ok: true` for completed runs; failed runs still write a
|
||||
summary with `ok: false` and a `failure` object before returning a non-zero
|
||||
exit code.
|
||||
|
||||
Remove the shared work volume between repeated manual runs when you do not use
|
||||
a unique `BENCH_SPLIT_RUN_ID`:
|
||||
|
||||
```bash
|
||||
docker compose -f test/bench-network/compose.yml --profile p2p-split down --volumes
|
||||
```
|
||||
|
||||
## Shimmed CouchDB benchmark
|
||||
|
||||
The optional `shim` profile runs a CouchDB benchmark through a TCP forwarding
|
||||
|
||||
@@ -160,6 +160,91 @@ services:
|
||||
volumes:
|
||||
- ./bench-results:/workspace/src/apps/cli/testdeno/bench-results
|
||||
|
||||
p2p-split-host:
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: test/bench-network/Dockerfile.runner
|
||||
profiles:
|
||||
- p2p-split
|
||||
depends_on:
|
||||
nostr-relay:
|
||||
condition: service_healthy
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
environment:
|
||||
BENCH_COMMAND: p2p-split-node
|
||||
BENCH_P2P_SPLIT_ROLE: host
|
||||
BENCH_SPLIT_RUN_ID: ${BENCH_SPLIT_RUN_ID:-bench-split-run}
|
||||
BENCH_SPLIT_WORK_ROOT: /p2p-work
|
||||
BENCH_SPLIT_RESULT_ROOT: /workspace/src/apps/cli/testdeno/bench-results
|
||||
BENCH_RELAY: ws://nostr-relay:7777/
|
||||
BENCH_APP_ID: ${BENCH_APP_ID:-self-hosted-livesync-cli-benchmark}
|
||||
BENCH_ROOM_ID: ${BENCH_ROOM_ID:-bench-split-room}
|
||||
BENCH_PASSPHRASE: ${BENCH_PASSPHRASE:-bench-split-passphrase}
|
||||
BENCH_TURN_SERVERS: ${BENCH_TURN_SERVERS:-}
|
||||
BENCH_MD_FILE_COUNT: ${BENCH_MD_FILE_COUNT:-20}
|
||||
BENCH_MD_MIN_SIZE_BYTES: ${BENCH_MD_MIN_SIZE_BYTES:-512}
|
||||
BENCH_MD_MAX_SIZE_BYTES: ${BENCH_MD_MAX_SIZE_BYTES:-2048}
|
||||
BENCH_BIN_FILE_COUNT: ${BENCH_BIN_FILE_COUNT:-5}
|
||||
BENCH_BIN_SIZE_BYTES: ${BENCH_BIN_SIZE_BYTES:-8192}
|
||||
BENCH_SYNC_TIMEOUT: ${BENCH_SYNC_TIMEOUT:-300}
|
||||
BENCH_PEERS_TIMEOUT: ${BENCH_PEERS_TIMEOUT:-60}
|
||||
BENCH_NETEM_ENABLED: ${BENCH_NETEM_ENABLED:-1}
|
||||
BENCH_NETWORK_PROFILE: ${BENCH_NETWORK_PROFILE:-home-wifi}
|
||||
NETEM_PROFILE: ${NETEM_PROFILE:-home-wifi}
|
||||
NETEM_INTERFACE: ${NETEM_INTERFACE:-eth0}
|
||||
NETEM_DELAY_MS: ${NETEM_DELAY_MS:-20}
|
||||
NETEM_JITTER_MS: ${NETEM_JITTER_MS:-5}
|
||||
NETEM_LOSS_PERCENT: ${NETEM_LOSS_PERCENT:-0.1}
|
||||
NETEM_BANDWIDTH_MBIT: ${NETEM_BANDWIDTH_MBIT:-100}
|
||||
NETEM_MTU: ${NETEM_MTU:-1500}
|
||||
LIVESYNC_P2P_RELAY_READY_TIMEOUT_MS: ${LIVESYNC_P2P_RELAY_READY_TIMEOUT_MS:-60000}
|
||||
LIVESYNC_TEST_TEE: ${BENCH_LIVESYNC_TEST_TEE:-0}
|
||||
volumes:
|
||||
- p2p-split-work:/p2p-work
|
||||
- ./bench-results:/workspace/src/apps/cli/testdeno/bench-results
|
||||
|
||||
p2p-split-client:
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: test/bench-network/Dockerfile.runner
|
||||
profiles:
|
||||
- p2p-split
|
||||
depends_on:
|
||||
nostr-relay:
|
||||
condition: service_healthy
|
||||
p2p-split-host:
|
||||
condition: service_started
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
environment:
|
||||
BENCH_COMMAND: p2p-split-node
|
||||
BENCH_P2P_SPLIT_ROLE: client
|
||||
BENCH_SPLIT_RUN_ID: ${BENCH_SPLIT_RUN_ID:-bench-split-run}
|
||||
BENCH_SPLIT_WORK_ROOT: /p2p-work
|
||||
BENCH_SPLIT_RESULT_ROOT: /workspace/src/apps/cli/testdeno/bench-results
|
||||
BENCH_RELAY: ws://nostr-relay:7777/
|
||||
BENCH_APP_ID: ${BENCH_APP_ID:-self-hosted-livesync-cli-benchmark}
|
||||
BENCH_ROOM_ID: ${BENCH_ROOM_ID:-bench-split-room}
|
||||
BENCH_PASSPHRASE: ${BENCH_PASSPHRASE:-bench-split-passphrase}
|
||||
BENCH_TURN_SERVERS: ${BENCH_TURN_SERVERS:-}
|
||||
BENCH_SYNC_TIMEOUT: ${BENCH_SYNC_TIMEOUT:-300}
|
||||
BENCH_PEERS_TIMEOUT: ${BENCH_PEERS_TIMEOUT:-60}
|
||||
BENCH_NETEM_ENABLED: ${BENCH_NETEM_ENABLED:-1}
|
||||
BENCH_NETWORK_PROFILE: ${BENCH_NETWORK_PROFILE:-home-wifi}
|
||||
NETEM_PROFILE: ${NETEM_PROFILE:-home-wifi}
|
||||
NETEM_INTERFACE: ${NETEM_INTERFACE:-eth0}
|
||||
NETEM_DELAY_MS: ${NETEM_DELAY_MS:-20}
|
||||
NETEM_JITTER_MS: ${NETEM_JITTER_MS:-5}
|
||||
NETEM_LOSS_PERCENT: ${NETEM_LOSS_PERCENT:-0.1}
|
||||
NETEM_BANDWIDTH_MBIT: ${NETEM_BANDWIDTH_MBIT:-100}
|
||||
NETEM_MTU: ${NETEM_MTU:-1500}
|
||||
LIVESYNC_P2P_RELAY_READY_TIMEOUT_MS: ${LIVESYNC_P2P_RELAY_READY_TIMEOUT_MS:-60000}
|
||||
LIVESYNC_TEST_TEE: ${BENCH_LIVESYNC_TEST_TEE:-0}
|
||||
volumes:
|
||||
- p2p-split-work:/p2p-work
|
||||
- ./bench-results:/workspace/src/apps/cli/testdeno/bench-results
|
||||
|
||||
netem-smoke:
|
||||
build:
|
||||
context: ../..
|
||||
@@ -179,3 +264,6 @@ services:
|
||||
NETEM_RESULT_ROOT: /bench-results
|
||||
volumes:
|
||||
- ./bench-results:/bench-results
|
||||
|
||||
volumes:
|
||||
p2p-split-work:
|
||||
|
||||
@@ -8,9 +8,12 @@ case "${BENCH_COMMAND:-cases}" in
|
||||
latency-sweep)
|
||||
exec deno task bench:latency-sweep
|
||||
;;
|
||||
p2p-split-node)
|
||||
exec deno task bench:p2p-split-node
|
||||
;;
|
||||
*)
|
||||
echo "Unknown BENCH_COMMAND: ${BENCH_COMMAND}" >&2
|
||||
echo "Expected one of: cases, latency-sweep" >&2
|
||||
echo "Expected one of: cases, latency-sweep, p2p-split-node" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user