Skip to content

Commit 2d53623

Browse files
test(case2): direct-gRPC cross-host RTT probe (raw-bytes echo, no SSH tunnel)
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
1 parent d3a0a49 commit 2d53623

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Direct-gRPC cross-host round-trip probe (no SSH tunnel).
2+
3+
Compares a REAL gRPC channel against the reverse-SSH-tunnel raw-socket path for
4+
the Case-2 per-block proposer<->verifier payload. Raw-bytes unary RPC (no proto
5+
codegen): the server echoes the payload; the client times the round-trip for a
6+
range of payload sizes.
7+
8+
Roles:
9+
--role server --bind 0.0.0.0:PORT (run on the reachable host, e.g. GPU)
10+
--role client --addr HOST:PORT --payloads 64,160000 --reps 12
11+
12+
Run the server on the GPU bound to a vast-mapped internal port; connect from the
13+
cloud agent to PUBLIC_IPADDR:<mapped public port>. That round-trip traverses the
14+
real network over HTTP/2 with gRPC flow control — no SSH encryption/relay hop.
15+
"""
16+
17+
from __future__ import annotations
18+
19+
import argparse
20+
import time
21+
from concurrent import futures
22+
from typing import List
23+
24+
import grpc
25+
26+
_IDENT = lambda b: b # noqa: E731 (raw-bytes serializer)
27+
_METHOD = "/echo.Echo/Echo"
28+
_BIG = 256 * 1024 * 1024
29+
_OPTS = [("grpc.max_send_message_length", _BIG),
30+
("grpc.max_receive_message_length", _BIG)]
31+
32+
33+
def _serve(bind: str) -> int:
34+
def handler(request: bytes, context) -> bytes: # echo
35+
return request
36+
h = grpc.method_handlers_generic_handler(
37+
"echo.Echo",
38+
{"Echo": grpc.unary_unary_rpc_method_handler(
39+
handler, request_deserializer=_IDENT, response_serializer=_IDENT)})
40+
server = grpc.server(futures.ThreadPoolExecutor(max_workers=16), options=_OPTS)
41+
server.add_generic_rpc_handlers((h,))
42+
server.add_insecure_port(bind)
43+
server.start()
44+
print(f"[grpc-echo] serving on {bind}", flush=True)
45+
server.wait_for_termination()
46+
return 0
47+
48+
49+
def _client(addr: str, payloads: List[int], reps: int) -> int:
50+
channel = grpc.insecure_channel(
51+
addr, options=_OPTS + [("grpc.enable_http_proxy", 0)])
52+
echo = channel.unary_unary(_METHOD, request_serializer=_IDENT,
53+
response_deserializer=_IDENT)
54+
grpc.channel_ready_future(channel).result(timeout=30)
55+
for nb in payloads:
56+
p = b"x" * nb
57+
ts = []
58+
for _ in range(reps):
59+
t = time.perf_counter()
60+
r = echo(p)
61+
ts.append((time.perf_counter() - t) * 1000.0)
62+
assert len(r) == nb
63+
ts.sort()
64+
med = ts[len(ts) // 2]
65+
print(f"[grpc-echo] payload {nb:8d} B -> median RTT {med:.1f} ms "
66+
f"(min {ts[0]:.1f}, max {ts[-1]:.1f})", flush=True)
67+
channel.close()
68+
return 0
69+
70+
71+
def main() -> int:
72+
ap = argparse.ArgumentParser(description=__doc__)
73+
ap.add_argument("--role", required=True, choices=["server", "client"])
74+
ap.add_argument("--bind", default="0.0.0.0:72299")
75+
ap.add_argument("--addr", default="127.0.0.1:72299")
76+
ap.add_argument("--payloads", default="64,40000,80000,160000")
77+
ap.add_argument("--reps", type=int, default=12)
78+
args = ap.parse_args()
79+
if args.role == "server":
80+
return _serve(args.bind)
81+
return _client(args.addr, [int(x) for x in args.payloads.split(",") if x.strip()],
82+
args.reps)
83+
84+
85+
if __name__ == "__main__":
86+
raise SystemExit(main())

0 commit comments

Comments
 (0)