第23話で完成した字幕streamが、左の台で青く光っていた。
一つ欠けたら、最後の一行を正しく組み立てられないdataだ。
右の台では、live microphoneの音声波が流れている。
新しい波の後ろから、遅れた古い一片が転がってきた。
イトは、その一片を現在の声へ押し込もうとした。
話し手は、もう次の音を発している。
古い一片を入れる間、いま届いている波が入口でつかえた。
remote stageの口元と音が、少しずれた。
イト
字幕では、欠けた一片を待って正解だった。でもlive音声まで同じように待たせたら、いまの声が遅れる
ユイ
二つのdataは、失ったときに困ることが違います
ピコ
その違いから、transportを選んでみよう
remote stageでは、十秒後に短い実演が始まる。
開始前に、二つを届けなければならない。
欠けてはいけないopening subtitle data。
待ち時間を増やしたくないlive voice data。
十秒は、このラボだけのstage gateだ。
どちらにも同じ一回のdatagram lossが起こるtestをする。
全部TCPにしたtest
イトはまず、二つともTCPのstreamへ入れた。
subtitle dataは、前話と同じように順番を持って流れる。
middle segmentが失われる。
receiverは後ろのbytesを先にapplicationへ渡さず、gapが埋まるのを待った。
retransmissionが届くと、subtitle gateは正しく開いた。
一方、live voice streamでも一片が失われた。
後ろには、新しいvoice bytesが届いている。
でも同じTCP streamでは、missing bytesより後ろを順番どおりにapplicationへ渡すため、gapが埋まるまで待つ。
音は欠けにくい。
その代わり、このtrialでは話し手の口元より再生が遅れた。
マコト
TCPのreliable, in-order byte streamは、subtitleには欲しいserviceだね
イト
でもlive音声では、古い一片を待つcostが見えた
ピコ
TCPが悪いのではなく、このvoice applicationが何を優先するかとの組み合わせだよ
TCPは、IETFの現行標準RFC 9293が定めるreliable, in-order byte-stream serviceをapplicationへ提供する。
「TCPだから遅い」と決めつけるのではない。
このserviceのどこに価値があり、どこで待ちがcostになるかを見る。
stage gateは、残り七秒。
全部bare UDPにしたtest
次にイトは、二つともbare UDP datagramへ載せた。
live voiceの一片が失われる。
UDP自身は、その一片をretransmitしない。
後ろの新しいdatagramを、UDPがmissing pieceのために保留するわけではない。
remote sideでは一瞬だけwaveに穴が開き、次の新しい音が続いた。
今度は口元とのずれが広がらない。
けれどsubtitle dataでも、middle datagramが失われた。
UDP自身は、欠けを補って順番どおりのbyte streamに戻してくれない。
remote subtitleには中央の空白が残り、gateは開かなかった。
イト
UDPに入れただけで、live音声がうまくなるわけじゃない。穴をどう扱うかは、まだ何も決めていない
ユイ
subtitle側も、必要なreliabilityを誰も実装しなければ欠けたままです
ピコ
UDPは『何もしなくてよい高速レーン』ではないんだ
UDPはconnection setupのあるTCP streamとは違い、最小限のdatagram serviceを提供する。
しかし、built-inのretransmission、in-order delivery、flow control、congestion controlは持たない。
IETFのUDP Usage Guidelines RFC 8085は、UDP applicationもInternet上で適切なcongestion controlを行い、必要なreliabilityやmessage sizeなどを設計するよう求めている。
「待たない」と「無制限に送り続ける」は、まったく別だ。
stage gateは、残り四秒になった。
同じtransportに入れない
操作台に三枚の設計cardが開いた。
- subtitleもlive voiceも、TCP一streamへ入れる
- subtitleもlive voiceも、bare UDPへ入れる
- subtitleはreliable in-order serviceへ置き、live voiceはUDPを土台にapplication protocolでfreshness / loss / congestion policyを持つ
一番目なら、subtitleは完成する。
でも、このvoice trialではmissing old dataがcurrent playoutを待たせる。
二番目なら、voiceの新しいdatagramは進む。
でも、subtitleを完成させるreliabilityがない。
イトは三番目のcardを持ち上げた。
まず、subtitle trayをTCP endpoint ledgerへ戻す。
次に、live voice trayをUDP baseへ置いた。
ただし、そのままsend leverは押さない。
voice application側へ、三つの小さなpolicy tokenを置く。
- datagramの順序とplayout時刻を見分ける印
- deadlineを過ぎた古い一片をcurrent playoutへ戻さない条件
- network feedbackに合わせてsend rateを抑える条件
イト
UDPに丸投げしない。voiceで必要な順番と時刻をapplication側で見て、遅すぎる一片は捨てる。送りすぎない制御も残す
マコト
subtitleは完全性、voiceはfreshness。守りたい結果から責任を置いたんだね
ピコ
その設計を、この一回のlossで試そう
二つのtrayを分けたのは、ピコではない。
同じtransportへ押し込むのをやめ、UDPの上へ必要なpolicyを残したのはイトだった。
一つは補い、一つは手放した
二つのtest streamが、同時に動いた。
subtitle側でmiddle IP datagramが失われる。
TCP endpointはgapを検出し、missing dataをretransmitした。
receiverでstreamがそろい、opening subtitleが完全な形で灯る。
live voice側でも、一つのUDP datagramが遅れた。
新しいvoice datagramは、すでにplayout時刻へ近づいている。
イトはlate pieceをcurrent waveへ押し込まなかった。
deadline trayへ移す。
このlab applicationは短いgapを小さくconcealし、新しい音を再生した。
一瞬だけ音の薄い箇所があった。
それでも話し手の口元と声は、大きく離れずに進む。
stage gateは、一秒を残して開いた。

成功したのは、このlabのone subtitle / one voice trialだ。
すべてのvoice applicationが同じgapを許せるわけではない。loss率、delay、codec、network、会話の目的で結果は変わる。
UDPの上にも、reliable streamを作れる
イトは、UDP baseに置いたvoice policyを見て首をかしげた。
「上で機能を足せるなら、UDPの上にreliableな通信も作れる?」
遠くの棚から、複数のstreamを持つ新しい装置が現れた。
UDP datagramを土台にしながら、loss detection、reliable delivery、congestion control、ordered streamを備えている。
QUICだ。
IETFのRFC 9000は、QUIC packetをUDP datagramで運びながら、reliable deliveryとcongestion controlに必要なfeedback、application向けのordered byte streamsを提供するtransportを定めている。
だから、次の二つはどちらも誤りだ。
UDPなら、必ず速い。
UDPなら、reliabilityを持てない。
見るべきなのは、最終的にapplicationへどんなserviceを提供し、その機能をどのprotocolが引き受けるかだ。
Webでも、HTTP/1.1 / HTTP/2はTCPを使い、HTTP/3はUDP上のQUICを使う。application名だけでTCP / UDPを固定しない。
関連ガイド「TCPとUDPの違い」では、stream / datagram、reliability、ordering、connection stateを比較表で確認できる。
選ばなかったものも、costとして残る
subtitle側では、missing dataを待つ時間とretransmissionが残った。
voice側では、一瞬の薄い音とapplication protocolの複雑さが残った。
UDP側もcongestion responseを外していない。
TCP側も「遅いから負け」ではない。
イトは、二つのresult cardを重ねなかった。
片方は完全性。
もう片方は、このtrialでのfreshness。
同じ物差しで優勝を決める話ではなかった。
次回:TCPは、欠けをどう見つけた?
stageのsubtitleは、欠けなく灯っている。
しかしsource TCP ledgerでは、三つのACK pulseと一つのtimer ringがまだ動いていた。
どのACKが、どこまで届いたと知らせたのか。
同じACKが続くと、senderは何を見るのか。
timerが先に尽きたら、何を送り直すのか。
イトは、subtitle trayの裏側へ回った。
次回、ピコルート第25話。
TCPは、missing dataを見ていないのに、どうやって欠けを見つける?

