6.0 KiB
Étude 0.3.5 — caractérisation bornée WebSocket / WebTransport
Objet
Cette étude définit la méthode de 0.3.5-alpha.10. Elle ne cherche pas à produire un benchmark général de WebSocket contre WebTransport, mais à caractériser les deux implémentations dans games.sasedev, sur loopback, avec le même contrat fiable et des charges bornées.
Les valeurs dépendent de la machine, du kernel, du scheduler, du profil Cargo et de l'état local du système. Elles ne doivent pas être extrapolées à un réseau mobile, à Internet, à un navigateur distant ou à une charge serveur multi-utilisateur.
Outil
Le launcher technique est :
crates/apps/game-realtime-transport-measure
Exécution de référence :
cargo run --release -p game-realtime-transport-measure
Le profil --release est recommandé pour réduire le poids du code de mesure lui-même. La gate peut aussi exécuter le profil debug pour vérifier le fonctionnement, mais les chiffres debug ne doivent pas être comparés à des chiffres release.
Préparation commune
Les deux chemins fiables utilisent leurs configurations produit par défaut et le contrat RealtimeConnection.
WebSocket :
TCP loopback
ws://127.0.0.1:<port>/measure
Tokio + tokio-tungstenite
WebTransport :
UDP loopback
https://127.0.0.1:<port>/measure
QUIC + HTTP/3
certificat P-256 loopback en mémoire
pin SHA-256 exact
stream bidirectionnel primaire
L'outil ne configure ni loss artificiel, ni jitter, ni bandwidth shaping.
Établissement
Pour chaque backend :
samples = 8
WebSocket mesure du début du connect/accept jusqu'à la connexion établie après handshake.
WebTransport mesure jusqu'au chemin fiable utilisable : session WebTransport établie et stream bidirectionnel primaire ouvert/accepté.
Le rapport fournit :
min_us
median_us
p95_us
max_us
Les premières connexions peuvent inclure des coûts froids ; aucun échantillon d'établissement n'est supprimé.
RTT fiable
Charge :
warmup = 16
samples = 128
payload = 32 octets
Le client envoie un message et attend l'écho exact avant d'envoyer le suivant. Seuls les 128 échantillons post-warmup entrent dans le résumé.
Le résultat mesure donc le RTT applicatif du contrat RealtimeConnection, pas le RTT brut TCP/QUIC.
Throughput fiable
Charge :
messages = 128
payload = 64 KiB
volume utile = 8 MiB
Le client envoie les messages sans ACK applicatif intermédiaire. Le serveur draine exactement les 128 messages puis renvoie un ACK final. Le chronomètre client s'arrête à réception de cet ACK.
Le résultat fournit :
elapsed_us
mib_per_s
messages_per_s
Il inclut le framing du backend, les copies/allocation du POC et la backpressure réellement appliquée par les wrappers.
Fenêtre de messages en vol
Charge :
messages = 64
payload = 1 KiB
Le client émet 64 messages sans ACK applicatif intermédiaire, puis attend un ACK unique après drainage côté serveur.
Cette mesure ne prétend pas connaître le nombre exact de paquets réseau simultanément en vol. Elle valide une fenêtre applicative bornée de 64 messages non acquittés individuellement et rapporte son temps de complétion.
Datagram WebTransport
Le datagram est mesuré séparément du contrat fiable :
attempted = 64
payload = min(256, client_max_datagram_size, server_max_datagram_size)
Le client émet les 64 datagrams puis le serveur les reçoit jusqu'à atteindre 64 ou jusqu'à une attente locale de 250 ms sans nouveau datagram.
Le rapport fournit :
attempted
received
receive_ratio
payload_bytes
client_max
server_max
elapsed_us
receive_ratio = 1.0 sur loopback ne transforme pas les datagrams en transport fiable. Une perte observée n'est pas automatiquement un défaut de protocole : elle doit être interprétée avec la sémantique non fiable de WebTransport.
Format de sortie
Chaque mesure utilise une ligne stable :
MEASURE transport=<...> metric=<...> ...
La fin normale est :
CONCLUSION webtransport=retain scope=second-backend reason=reliable-browser-fallback-datagram-capabilities
game-realtime-transport-measure: PASS
Lecture des résultats
Aucun seuil automatique « gagnant/perdant » n'est défini. Une différence loopback de quelques microsecondes ou quelques pourcents n'a pas de valeur produit suffisante à elle seule.
Les dimensions utiles sont :
- absence d'échec ou de timeout inattendu ;
- ordre de grandeur de l'établissement ;
- stabilité médiane/p95 du RTT ;
- absence d'effondrement évident du throughput fiable ;
- capacité à soutenir la fenêtre applicative bornée ;
- observation distincte de la capacité datagram.
Conclusion technique retenue
Décision consolidée pour 0.3.5 : retained.
Cela signifie : conserver WebTransport comme second backend realtime expérimental/évolutif à côté de WebSocket. Cette décision repose sur l'ensemble des preuves 0.3.5 déjà acquises :
- backend natif fiable ;
- client navigateur/WASM ;
- smoke navigateur réel ;
- robustesse et deadlines ;
- fallback WebSocket strictement classifié ;
- datagrams optionnels backend-spécifiques.
Cette conclusion ne signifie pas que WebTransport est déclaré plus rapide que WebSocket. Les runs alpha.10.fix.1 et beta.1 montrent au contraire des avantages différents selon le pattern mesuré : établissement plus coûteux pour WebTransport, RTT local plus faible dans ces runs, throughput 64 KiB supérieur pour WebSocket et fenêtre 1 KiB nettement supérieure pour WebTransport. Ces écarts servent à caractériser les wrappers actuels, pas à produire un classement général.
La validation large a ensuite confirmé le workspace complet, les smokes natifs, le chemin navigateur/WASM réel et la cross-compilation Android ARM64/API 21. Les valeurs exactes des runs validés restent dans history/0.3.5/alpha.10.fix.1.md et history/0.3.5/beta.1.fix.1.md.