Files
shadowsocks-libev/tests/measure_udp.py
Max Lv 201e70c4bd Modernize C builds with offline dependencies and portable runtime helpers (#3050)
Bundle pinned offline dependencies, remove libcork/libipset and submodule requirements, and add portable runtime helpers with relocatable static/shared library installations.

Add Clang static build validation for Linux/musl, macOS and Windows, real TCP/UDP and SIP003 interoperability coverage, and recorded performance tradeoffs. All 21 hosted checks pass at the reviewed PR head 8d504e6218.
2026-09-11 13:42:11 +08:00

56 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Loopback UDP echo measurement; includes Python/SOCKS overhead, not a capacity test."""
import argparse
import base64
import json
import os
from pathlib import Path
import socket
import struct
import threading
import time
from interop import UDPOrigin, UDPHandler, free_port, peers, socks
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--bin", required=True, type=Path)
parser.add_argument("--output", required=True, type=Path)
parser.add_argument("--count", type=int, default=2000)
parser.add_argument("--repeat", type=int, default=3)
args = parser.parse_args()
results = []
with UDPOrigin(("127.0.0.1", 0), UDPHandler) as origin:
threading.Thread(target=origin.serve_forever, daemon=True).start()
try:
for method in ("aes-128-gcm", "aes-256-gcm", "chacha20-ietf-poly1305"):
server_port, local_port = free_port(), free_port()
key = base64.b64encode(os.urandom(32)).decode("ascii")
common = ["-s", "127.0.0.1", "-p", str(server_port), "-m", method, "-k", key, "-u"]
commands = [[str(args.bin.resolve() / "ss-server"), *common],
[str(args.bin.resolve() / "ss-local"), *common, "-l", str(local_port)]]
with peers(commands, [server_port, local_port]):
control, relay = socks(local_port, 3, ("0.0.0.0", 0))
with control, socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as udp:
udp.settimeout(5)
relay = ("127.0.0.1", relay[1])
prefix = b"\0\0\0\x01\x7f\0\0\x01" + struct.pack("!H", origin.server_address[1])
for trial in range(args.repeat):
start = time.perf_counter()
for sequence in range(args.count):
payload = struct.pack("!I", sequence) + bytes(1196)
udp.sendto(prefix + payload, relay)
response, sender = udp.recvfrom(65536)
assert sender[1] == relay[1] and response[10:] == payload
elapsed = time.perf_counter() - start
results.append(dict(cipher=method, trial=trial, packets=args.count,
payload_bytes=1200, seconds=elapsed,
payload_mbps=args.count * 1200 * 8 / elapsed / 1e6))
finally:
origin.shutdown()
args.output.write_text(json.dumps(results, indent=2) + "\n")
if __name__ == "__main__":
main()