mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-09 14:23:09 +00:00
Add CouchDB netem shim benchmark
This commit is contained in:
@@ -23,6 +23,9 @@ type BenchmarkConfig = {
|
|||||||
passphrase: string;
|
passphrase: string;
|
||||||
encrypt: boolean;
|
encrypt: boolean;
|
||||||
managedCouchdb: boolean;
|
managedCouchdb: boolean;
|
||||||
|
simulationTier: string;
|
||||||
|
networkProfile: string;
|
||||||
|
networkModel: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function readEnvString(name: string, fallback: string): string {
|
function readEnvString(name: string, fallback: string): string {
|
||||||
@@ -90,6 +93,9 @@ function buildConfig(): BenchmarkConfig {
|
|||||||
passphrase: readEnvString("BENCH_PASSPHRASE", `bench-${Date.now()}`),
|
passphrase: readEnvString("BENCH_PASSPHRASE", `bench-${Date.now()}`),
|
||||||
encrypt: readEnvBool("BENCH_ENCRYPT", true),
|
encrypt: readEnvBool("BENCH_ENCRYPT", true),
|
||||||
managedCouchdb: readEnvBool("BENCH_COUCHDB_MANAGED", true),
|
managedCouchdb: readEnvBool("BENCH_COUCHDB_MANAGED", true),
|
||||||
|
simulationTier: readEnvString("BENCH_SIMULATION_TIER", "1"),
|
||||||
|
networkProfile: readEnvString("BENCH_NETWORK_PROFILE", "http-latency-proxy"),
|
||||||
|
networkModel: readEnvString("BENCH_NETWORK_MODEL", "local-http-proxy"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +291,9 @@ async function main(): Promise<void> {
|
|||||||
couchdbProxyUri: config.couchdbProxyUri,
|
couchdbProxyUri: config.couchdbProxyUri,
|
||||||
couchdbDbname: config.couchdbDbname,
|
couchdbDbname: config.couchdbDbname,
|
||||||
managedCouchdb: config.managedCouchdb,
|
managedCouchdb: config.managedCouchdb,
|
||||||
|
simulationTier: config.simulationTier,
|
||||||
|
networkProfile: config.networkProfile,
|
||||||
|
networkModel: config.networkModel,
|
||||||
rttRequestedMs: config.requestedRttMs,
|
rttRequestedMs: config.requestedRttMs,
|
||||||
proxyApplied: proxy.applied,
|
proxyApplied: proxy.applied,
|
||||||
proxyNote: proxy.note,
|
proxyNote: proxy.note,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ function buildCases(): BenchmarkCase[] {
|
|||||||
const couchdbRtt = readEnvString("BENCH_COUCHDB_RTT_MS", "20");
|
const couchdbRtt = readEnvString("BENCH_COUCHDB_RTT_MS", "20");
|
||||||
const tetheringVpnRtt = readEnvString("BENCH_TETHERING_VPN_RTT_MS", "120");
|
const tetheringVpnRtt = readEnvString("BENCH_TETHERING_VPN_RTT_MS", "120");
|
||||||
const localTurnServers = readEnvString("BENCH_LOCAL_TURN_SERVERS", "turn:127.0.0.1:3478");
|
const localTurnServers = readEnvString("BENCH_LOCAL_TURN_SERVERS", "turn:127.0.0.1:3478");
|
||||||
|
const shimCouchdbUri = readEnvString("BENCH_SHIM_COUCHDB_URI", "http://couchdb-shim:5984");
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -79,6 +80,40 @@ function buildCases(): BenchmarkCase[] {
|
|||||||
BENCH_COUCHDB_RTT_MS: tetheringVpnRtt,
|
BENCH_COUCHDB_RTT_MS: tetheringVpnRtt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "couchdb-netem-home-wifi",
|
||||||
|
runner: "couchdb",
|
||||||
|
description:
|
||||||
|
"Tier 2 CouchDB path through the Compose netem TCP shim using the home-wifi profile.",
|
||||||
|
dataPath: "Device A -> netem TCP shim -> CouchDB -> netem TCP shim -> Device B",
|
||||||
|
trustBoundary: "CouchDB operator and constrained network shim",
|
||||||
|
env: {
|
||||||
|
...base,
|
||||||
|
BENCH_CASE: "couchdb-netem-home-wifi",
|
||||||
|
BENCH_COUCHDB_BACKEND_URI: shimCouchdbUri,
|
||||||
|
BENCH_COUCHDB_RTT_MS: "1",
|
||||||
|
BENCH_SIMULATION_TIER: "2",
|
||||||
|
BENCH_NETWORK_PROFILE: "home-wifi",
|
||||||
|
BENCH_NETWORK_MODEL: "compose-netem-tcp-shim",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "couchdb-netem-tethering-vpn",
|
||||||
|
runner: "couchdb",
|
||||||
|
description:
|
||||||
|
"Tier 2 CouchDB path through the Compose netem TCP shim using a tethering-vpn profile.",
|
||||||
|
dataPath: "Device A -> netem TCP shim -> CouchDB -> netem TCP shim -> Device B",
|
||||||
|
trustBoundary: "CouchDB operator and constrained smartphone/VPN-like network shim",
|
||||||
|
env: {
|
||||||
|
...base,
|
||||||
|
BENCH_CASE: "couchdb-netem-tethering-vpn",
|
||||||
|
BENCH_COUCHDB_BACKEND_URI: shimCouchdbUri,
|
||||||
|
BENCH_COUCHDB_RTT_MS: "1",
|
||||||
|
BENCH_SIMULATION_TIER: "2",
|
||||||
|
BENCH_NETWORK_PROFILE: "tethering-vpn",
|
||||||
|
BENCH_NETWORK_MODEL: "compose-netem-tcp-shim",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "p2p-smartphone-vpn-direct",
|
name: "p2p-smartphone-vpn-direct",
|
||||||
runner: "p2p",
|
runner: "p2p",
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM alpine:3.22
|
||||||
|
|
||||||
|
RUN apk add --no-cache iproute2 socat
|
||||||
|
|
||||||
|
COPY test/bench-network/netem-tcp-shim.sh /usr/local/bin/livesync-netem-tcp-shim
|
||||||
|
RUN chmod +x /usr/local/bin/livesync-netem-tcp-shim
|
||||||
|
|
||||||
|
CMD ["livesync-netem-tcp-shim"]
|
||||||
@@ -42,6 +42,8 @@ Available local cases:
|
|||||||
- `couchdb-baseline`
|
- `couchdb-baseline`
|
||||||
- `p2p-direct-local`
|
- `p2p-direct-local`
|
||||||
- `couchdb-tethering-vpn-proxy`
|
- `couchdb-tethering-vpn-proxy`
|
||||||
|
- `couchdb-netem-home-wifi`
|
||||||
|
- `couchdb-netem-tethering-vpn`
|
||||||
- `p2p-smartphone-vpn-direct`
|
- `p2p-smartphone-vpn-direct`
|
||||||
- `p2p-user-turn`
|
- `p2p-user-turn`
|
||||||
|
|
||||||
@@ -130,3 +132,31 @@ NETEM_BANDWIDTH_MBIT=10 \
|
|||||||
NETEM_MTU=1380 \
|
NETEM_MTU=1380 \
|
||||||
docker compose -f test/bench-network/compose.yml --profile netem run --rm netem-smoke
|
docker compose -f test/bench-network/compose.yml --profile netem run --rm netem-smoke
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Shimmed CouchDB benchmark
|
||||||
|
|
||||||
|
The optional `shim` profile runs a CouchDB benchmark through a TCP forwarding
|
||||||
|
container that applies `tc netem`. This is a manual Tier 2 synchronisation
|
||||||
|
measurement path; it is intentionally separate from required pull-request CI.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f test/bench-network/compose.yml --profile shim run --rm bench-runner-shim
|
||||||
|
```
|
||||||
|
|
||||||
|
The default profile is `home-wifi`. A smartphone/VPN-like profile can be
|
||||||
|
requested by overriding both the shim parameters and the benchmark case:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NETEM_PROFILE=tethering-vpn \
|
||||||
|
NETEM_DELAY_MS=140 \
|
||||||
|
NETEM_JITTER_MS=50 \
|
||||||
|
NETEM_LOSS_PERCENT=1.0 \
|
||||||
|
NETEM_BANDWIDTH_MBIT=10 \
|
||||||
|
NETEM_MTU=1380 \
|
||||||
|
BENCH_CASES=couchdb-netem-tethering-vpn \
|
||||||
|
docker compose -f test/bench-network/compose.yml --profile shim run --rm bench-runner-shim
|
||||||
|
```
|
||||||
|
|
||||||
|
The benchmark result records `simulationTier`, `networkProfile`, and
|
||||||
|
`networkModel`. The shim also writes its applied `tc qdisc`, route, and
|
||||||
|
interface state under `test/bench-network/bench-results/`.
|
||||||
|
|||||||
@@ -98,6 +98,68 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./bench-results:/workspace/src/apps/cli/testdeno/bench-results
|
- ./bench-results:/workspace/src/apps/cli/testdeno/bench-results
|
||||||
|
|
||||||
|
couchdb-shim:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: test/bench-network/Dockerfile.shim
|
||||||
|
profiles:
|
||||||
|
- shim
|
||||||
|
depends_on:
|
||||||
|
couchdb:
|
||||||
|
condition: service_healthy
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
environment:
|
||||||
|
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}
|
||||||
|
NETEM_RESULT_ROOT: /bench-results
|
||||||
|
SHIM_LISTEN_PORT: 5984
|
||||||
|
SHIM_TARGET_HOST: couchdb
|
||||||
|
SHIM_TARGET_PORT: 5984
|
||||||
|
volumes:
|
||||||
|
- ./bench-results:/bench-results
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "nc -z 127.0.0.1 5984"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 30
|
||||||
|
|
||||||
|
bench-runner-shim:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: test/bench-network/Dockerfile.runner
|
||||||
|
profiles:
|
||||||
|
- shim
|
||||||
|
depends_on:
|
||||||
|
couchdb-shim:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
BENCH_COMMAND: ${BENCH_COMMAND:-cases}
|
||||||
|
BENCH_CASES: ${BENCH_CASES:-couchdb-netem-home-wifi}
|
||||||
|
BENCH_CASES_ROOT: /workspace/src/apps/cli/testdeno/bench-results
|
||||||
|
BENCH_SWEEP_ROOT: /workspace/src/apps/cli/testdeno/bench-results
|
||||||
|
BENCH_COUCHDB_MANAGED: "false"
|
||||||
|
BENCH_COUCHDB_BACKEND_URI: http://couchdb-shim:5984
|
||||||
|
BENCH_SHIM_COUCHDB_URI: http://couchdb-shim:5984
|
||||||
|
BENCH_COUCHDB_URI: http://127.0.0.1:15989
|
||||||
|
BENCH_COUCHDB_USER: ${BENCH_COUCHDB_USER:-admin}
|
||||||
|
BENCH_COUCHDB_PASSWORD: ${BENCH_COUCHDB_PASSWORD:-testpassword}
|
||||||
|
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_COUCHDB_RTT_MS: ${BENCH_COUCHDB_RTT_MS:-1}
|
||||||
|
BENCH_SYNC_TIMEOUT: ${BENCH_SYNC_TIMEOUT:-300}
|
||||||
|
BENCH_LIVESYNC_TEST_TEE: ${BENCH_LIVESYNC_TEST_TEE:-0}
|
||||||
|
volumes:
|
||||||
|
- ./bench-results:/workspace/src/apps/cli/testdeno/bench-results
|
||||||
|
|
||||||
netem-smoke:
|
netem-smoke:
|
||||||
build:
|
build:
|
||||||
context: ../..
|
context: ../..
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
profile="${NETEM_PROFILE:-home-wifi}"
|
||||||
|
iface="${NETEM_INTERFACE:-eth0}"
|
||||||
|
delay_ms="${NETEM_DELAY_MS:-20}"
|
||||||
|
jitter_ms="${NETEM_JITTER_MS:-5}"
|
||||||
|
loss_percent="${NETEM_LOSS_PERCENT:-0.1}"
|
||||||
|
bandwidth_mbit="${NETEM_BANDWIDTH_MBIT:-100}"
|
||||||
|
mtu="${NETEM_MTU:-1500}"
|
||||||
|
listen_port="${SHIM_LISTEN_PORT:-5984}"
|
||||||
|
target_host="${SHIM_TARGET_HOST:-couchdb}"
|
||||||
|
target_port="${SHIM_TARGET_PORT:-5984}"
|
||||||
|
out_root="${NETEM_RESULT_ROOT:-/bench-results}"
|
||||||
|
timestamp="$(date -u +%Y%m%d-%H%M%S)"
|
||||||
|
out_dir="${out_root}/netem-shim-${profile}-${timestamp}"
|
||||||
|
out_file="${out_dir}/summary.json"
|
||||||
|
|
||||||
|
json_lines() {
|
||||||
|
awk '
|
||||||
|
{
|
||||||
|
gsub(/\\/, "\\\\");
|
||||||
|
gsub(/"/, "\\\"");
|
||||||
|
printf "%s \"%s\"", (NR == 1 ? "" : ",\n"), $0;
|
||||||
|
}
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p "$out_dir"
|
||||||
|
|
||||||
|
if ! ip link show "$iface" >/dev/null 2>&1; then
|
||||||
|
echo "Network interface '$iface' was not found" >&2
|
||||||
|
ip addr >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
ip link set dev "$iface" mtu "$mtu"
|
||||||
|
tc qdisc del dev "$iface" root >/dev/null 2>&1 || true
|
||||||
|
tc qdisc add dev "$iface" root netem \
|
||||||
|
delay "${delay_ms}ms" "${jitter_ms}ms" \
|
||||||
|
loss "${loss_percent}%" \
|
||||||
|
rate "${bandwidth_mbit}mbit"
|
||||||
|
|
||||||
|
ip_addr="$(ip addr show "$iface" | json_lines)"
|
||||||
|
ip_route="$(ip route | json_lines)"
|
||||||
|
tc_qdisc="$(tc qdisc show dev "$iface" | json_lines)"
|
||||||
|
|
||||||
|
cat > "$out_file" <<EOF
|
||||||
|
{
|
||||||
|
"simulationTier": 2,
|
||||||
|
"mode": "netem-tcp-shim",
|
||||||
|
"profile": "$profile",
|
||||||
|
"interface": "$iface",
|
||||||
|
"listenPort": $listen_port,
|
||||||
|
"targetHost": "$target_host",
|
||||||
|
"targetPort": $target_port,
|
||||||
|
"netem": {
|
||||||
|
"delayMs": $delay_ms,
|
||||||
|
"jitterMs": $jitter_ms,
|
||||||
|
"lossPercent": $loss_percent,
|
||||||
|
"bandwidthMbit": $bandwidth_mbit,
|
||||||
|
"mtu": $mtu
|
||||||
|
},
|
||||||
|
"ipAddr": [
|
||||||
|
$ip_addr
|
||||||
|
],
|
||||||
|
"ipRoute": [
|
||||||
|
$ip_route
|
||||||
|
],
|
||||||
|
"tcQdisc": [
|
||||||
|
$tc_qdisc
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat "$out_file"
|
||||||
|
echo "[netem-shim] forwarding 0.0.0.0:${listen_port} to ${target_host}:${target_port}"
|
||||||
|
echo "[netem-shim] result file: $out_file"
|
||||||
|
|
||||||
|
exec socat "TCP-LISTEN:${listen_port},fork,reuseaddr" "TCP:${target_host}:${target_port}"
|
||||||
Reference in New Issue
Block a user