四個目のvideo chunkが、remote previewの空白へ戻った。
映像は完成した。
だが、時計の針はamberの締切線を越えている。
第28話で選んだ小分けは、lost chunk以外を先へ進ませた。
voiceも止めなかった。
それでも、retryを待ったぶん、最後のcutは一拍遅れた。
ラボの壁では、次のrehearsalまでの輪が六つ、順に消えていく。
今度はremote screenへ青いcueを送り、返ってきたacknowledgementでラボのlampを点ける。
往復がamber shutterの閉じる前に終わらなければ、映像の動きとlampがずれる。
イトは、sendとreturnの二本針を持つclock probeをqueueへ置いた。
「一回測れば、間に合うか分かるよね」
小さなprobeがremote screenへ走り、同じ印を持つreplyが戻った。
針は、clock faceの短い青帯で止まった。
今回のラボ表示では、18 ms。
イトは、その一個を大きな判定slotへはめた。
イト
よし。18 msなら、もう直った
ユイ
一回だけで決めるの?
イト
いちばん新しい数字だよ。古い遅れより正しいはず
ピコ
その数字が答えたのは、誰との、どの瞬間の、どこからどこまで?
イトはreplyを外さなかった。
短い針は、頼もしく見えた。
一番速い一回は、嘘ではなかった
rehearsalが始まった。
イトは次のanime cutを先に届けようと、video chunksを送信queueへ隙間なく並べた。
青い箱が、amber linkへ一個ずつ出る。
remote screenのcue frameが光った。
イトはcontrol probeを差し込む。
だがprobeは、すでに並んだvideo chunksを飛び越えなかった。
source queueの中で待つ。
一個。
もう一個。
amber shutterが閉じた。
その直後にreplyが戻り、lampが青く点いた。
映像の動きより、半拍遅い。
「18 msじゃなかった」
イトは、最初のreplyを握った。
ピコは首を振る。
「18 msだったよ。queueが空だった、あの一往復は」
最初のprobeは、嘘をついていない。
ただ、videoで埋まった本番の待ち時間を測っていなかった。
round-trip delayの測定方法を定めたRFC 2681は、一回の観測と、複数回から作るsampleを分けている。小さな値はpathが軽いときのpropagation / transmission delayを知る手がかりになる一方、それより増えた値は混雑による待ちを含みうる。
一番速い一回を捨てる必要はない。
それを「いつでも同じ」と言い換えないことが必要だった。
latencyは、区間を書かないと一つに決まらない
ピコが往復clockを開くと、一本のrouteが二本へほどけた。
outbound。
return。
source側の一つのclockが、probeを出す直前に始まり、対応するreplyを受け取った直後に止まる。
この差が、round-trip time(RTT) の一つの測り方だ。
往路だけの時間は、one-way delay。
復路だけにも、別のone-way delayがある。
二つは、いつもRTTの半分ずつとは限らない。
行きと帰りでrouterの列が違うことがある。
同じrouteに見えても、queueの混み方が違うことがある。
one-way delayを定義するRFC 7679とRFC 2681は、round tripがforwardとreverseという二つのpathをまとめて測る弱点を示している。
ユイ
latencyと言うだけでは、片道か往復かも分からないんですね
マコト
『押してから画面が動くまで』なら、networkの往復だけでなくapplicationの仕事も入るね
イト
じゃあ18 msは、animeが反応する全部の時間じゃない
ピコ
同じ言葉でも、startとfinishを先に決めよう
今回、イトが守りたいのは、control probeのsendから対応replyのreceiveまでだった。
remote applicationが映像をdecodeする時間ではない。
人がbuttonを押すまでの時間でもない。
「何が遅いか」を話す前に、時計の両端を置く。
それだけで、別の数字を同じlatencyとして争うのを避けられる。
RTT一個から、遅れた場所までは見えない
ピコは往復clockの内側へ、六つの透明なchamberを投影した。
- source hostが時刻を取り、packetをinterfaceへ渡すまでの差
- source queueで前のpacketを待つ時間
- linkへpacketを出し切るtransmission
- signalが距離を進むpropagation
- 途中のrouter queueと処理
- destinationがreplyを作り、reverse pathを戻る時間
RTTの針は、それらを足した結果として動く。
針が長いだけでは、どのchamberが増えたかを一意には決められない。
今回source queueが光ったのは、ラボが自分のqueueを観測できたからだ。
普通のRTT一個だけを見て、「Wi-Fi」「router」「server」のどれかを犯人にすることはできない。
Active Queue Managementの推奨をまとめたRFC 7567は、trafficを一時的に蓄えるqueueが必要な一方、過剰なqueueingはapplication性能を下げる不要なdelayにつながると説明している。
道幅が大きくても、列が伸びればcontrol packetは待つ。
道幅と待ち時間は、同じmeterではない。
pingは、小さな往復probeの結果
benchの端で、round-trip tokenが二つに開いた。
往路はEcho Request。
復路はEcho Reply。
ICMPを定めるRFC 792では、Echoで受け取ったdataをEcho Replyで返し、identifierとsequence numberでrequestとreplyを対応させられる。
一般的なpingは、このような小さなprobeを送り、対応するreplyまでの往復時間やlossを調べる道具だ。
だが、pingの数値は「Internet全体の速さ」ではない。
- 指定した相手との結果
- そのprobe type / sizeでの結果
- その時点のforward / reverse pathを合わせた結果
- application本体とは別のresponse処理を含む結果
相手やnetworkがEchoへreplyしない、または別の優先度で扱うこともある。
replyがないだけで、websiteやgame serverまで必ず停止しているとは決められない。
逆にpingが短くても、applicationの認証、database、renderingまで短いとは決められない。
pingは、原因を言い当てる判決ではない。
条件をそろえて変化を見るprobeだ。
三つの判定slot
amber shutterが、もう一度開いた。
rehearsalをやり直せるのは、あと一回。
benchに三つのslotが現れた。
- 一番速い18 msを採用する
- 軽いときのbaselineは残る。ただしloaded rehearsalを代表しない。
- 近いtest screenへ相手を替える
- 短い数字は出やすい。しかし守りたいremote screenを測っていない。
- 同じ相手をidle / loadedで繰り返し測り、送信burstを変える
- 本番に近い差を比べられる。ただしbulk videoを最短時間では送り切れないかもしれない。
ユイは二つ目の近いscreenを見た。
「成功だけ見せるなら、これがきれい」
マコトはclockを見たまま言った。
「でも、remote screenのcueは守れないね」
ピコは選ばなかった。
イトは最初の18 ms tokenをbaseline railへ移し、三つ目のslotを押した。
「速い数字を選ぶんじゃない。本番で増えた時間を探す」
イトは、同じ一往復を二つの条件で並べた
まず、videoを止めた。
同じremote screenへ、同じ大きさのprobeを七回送る。
reply tokenは、短い青帯の近くへまとまった。
一個だけを勝者にしない。
返らなかったprobeも隠さない。
次に、さっきと同じvideo burstをqueueへ入れた。
同じ相手へ、同じprobeを七回送る。
最初の二個は短い。
後ろのtokenは、amber、orangeへ伸びた。
一個はshutterの期限まで戻らず、dark slotに残った。
source queueの窓では、長い値になったprobeほど、video chunksの後ろで待っている。
イト
相手もprobeも同じ。videoを流したときだけ、列が伸びた
ユイ
だから今回は、少なくともラボの送信queueが増分の一つだと言える
ピコ
うん。RTTだけで場所を当てたんじゃない。条件を一つ変え、見えるqueueと結果をそろえた
七回は、Internetの標準回数ではない。
このrehearsalで、一回の偶然から離れるためにイトが選んだ回数だ。
測定の回数、間隔、timeout、相手、packet sizeが変われば、比較の意味も変わる。
イトは二列のrailへ、target、probe、load conditionの札を固定した。
イトは、videoを急いで詰め込まなかった
最後のrehearsalが始まった。
三つのcue frame用に、amber shutterが順に開く。
イトはvideo chunksをqueueから全部外した。
捨てたのではない。
一個ずつ、間隔を空けて戻す。
source applicationから送り出すburstを小さくし、control probeが入れるheadroomを残した。
networkに特別な優先laneを作ったわけではない。
途中のrouterへ保証を命令したわけでもない。
イトが制御できる送信側で、列を作りすぎない選択をした。
remote screenのcue frameが光った。
イトは自分でprobeを入れる。
青いtokenが、video chunkと次のchunkの間からamber linkへ出た。
replyが戻る。
往復clockの針は、shutterの手前で止まった。
ラボのlampが青く点く。
remote previewの動きと、同じ拍だった。
二回目も、三回目も、replyは違う位置で止まった。
完全に同じ値にはならない。
それでも三つとも、deadlineの内側だった。

イトは成功railを見て、すぐには笑わなかった。
隣のvideo progress barが、まだ終端へ届いていない。
反応を守った代わりに、送り終わりが遅れた
bulk videoを隙間なく送ったとき、preloadは早く終わった。
だがcontrol probeは長いqueueで待った。
間隔を空けた今、control RTTはdeadline内に収まった。
その代わり、video全体を送り終える時刻は後ろへずれた。
low latencyと、bulk dataを早く運び切ることは、同じ結果ではない。
今回のイトは、live cueを守るためにbulk completionを少し譲った。
別の場面なら、先にvideoを全部preloadする方がよいかもしれない。
pathの混雑が変われば、同じ間隔でもdeadlineを越えるかもしれない。
今回の三回成功は、永遠の保証ではない。
測る相手、interval、load、deadlineを記録し、条件が変われば測り直す。
それが、一個のping値をお守りにしない使い方だった。
latencyは、時計の名前ではなく境界の選び方
イトは、最初の18 ms tokenを捨てなかった。
idle baselineのrailへ置く。
その隣に、loaded時の長いtokensとdark timeout slotを残す。
一番速い一往復も、本番で遅れた一往復も、どちらも観測した事実だ。
違ったのは、条件だった。
latencyを見るときは、少なくとも次をそろえる。
- 何をstartとし、何をfinishとするか
- one-wayかround tripか、application全体か
- どの相手、どのprobeを測るか
- idleか、実際のloadがあるか
- 一回だけでなく、どのように繰り返したか
最初の一手は、clockのstartとfinishを決め、同じ相手・同じprobeを繰り返すことだ。
一回のpingで原因を決めない。
idleとloadを変えた差が再現したら、見えるqueueやapplication timingなど別の証拠と合わせる。
deadlineを越えるなら、送信burstを小さくするか、測定区間を分け直す。
pingは、その中のround-trip probeを作る一つの方法だ。
RTTは、二方向と複数の待ちを合わせた結果だ。
値が長いだけで、場所は決まらない。
イトが守ったのは、最小の数字ではなかった。
remote cueが間に合うという、先に決めたdeadlineだった。
次回:遅く送ったのに、反応は速くなった?
remote lampは、映像と同じ拍で三回点いた。
だがvideo progress barは、まだ少し残っている。
イトは、往復clockの隣にあるflow meterを見た。
時計の針は短くなった。
一秒の間に通ったbit札は、さっきより少ない。
「反応は間に合った。でも、運べた量は減った」
ピコは、二つのmeterの間へ一本の線を引いた。
次回、ピコルート第30話。
Mbpsは、何を数えている?
画面のむこう側をもっと知る
latency、RTT、pingとMbpsの違いを生活の場面で整理するなら、レイテンシとは?で確かめられます。

