トンネル化されたSSHセッションでoverallレイテンシを測定/報告する方法はありますか?
私の特定のセットアップは:
ローカルマシンのコンソールと、セッションを開いている最後のマシンとの間の遅延を確認したいのですが。
これを自分でやろうとして、これを思いついた。おそらくもっと簡単な方法がありますが、これが私が思いついた方法です。
まず、ベンチマークプログラムがSSH接続を介して通信するために使用するパイプを準備します。
$ mkfifo /tmp/up /tmp/down
次に、リモートコマンドを実行せずにControlMasterモードで接続を確立します。これにより、ホストをインタラクティブに認証できます。接続が確立すると、SSHはここでフォアグラウンドで「ハング」します。
$ ssh $Host -N -M -S /tmp/control
パラレルターミナルで、リモートcat
をバックグラウンドで実行します。待機時間を測定するのはエコーサーバーです。入力と出力はFIFOに接続されています。
$ ssh $Host -S /tmp/control cat </tmp/up >/tmp/down &
そして、小さなプログラムをベンチマークします(up
FIFOにバイトを送信し、down
FIFOからバイトを受信します):
$ python -m timeit -s 'import os' \
'os.write(3, "z"); z=os.read(4, 1); assert z=="z", "got %s" % z' \
3>/tmp/up 4</tmp/down
10 loops, best of 3: 24.6 msec per loop
この測定値は、明らかに往復遅延を示しています。実験を繰り返す必要がある場合は、最後の2つのコマンド(ssh
およびpython
)を再度実行します。
問題が発生した場合は、SSHを使用してください-v
フラグを使用して、より多くのデバッグ出力を取得します。
sshping
ユーティリティを参照してください: https://github.com/spook/sshping
例:
# sshping 172.16.47.143
--- Login: 1725 msec
--- Minimum Latency: 4046 nsec
--- Median Latency: 11026 nsec +/- 0 std dev
--- Average Latency: 178105 nsec
--- Maximum Latency: 8584886 nsec
--- Echo count: 1000 Bytes
--- Transfer Speed: 11694919 Bytes/second
# sshping --help
Usage: sshping [options] [user@]addr[:port]
SSH-based ping that measures interactive character echo latency
and file transfer throughput. Pronounced "shipping".
Options:
-c --count NCHARS Number of characters to echo, default 1000
-e --echocmd CMD Use CMD for echo command; default: cat > /dev/null
-h --help Print usage and exit
-i --identity FILE Identity file, ie ssh private keyfile
-p --password PWD Use password PWD (can be seen, use with care)
-r --runtime SECS Run for SECS seconds, instead of count limit
-t --tests e|s Run tests e=echo s=speed; default es=both
-v --verbose Show more output, use twice for more: -vv
@ nicht-verstehenによって提案されたいくつかの手順をスキップしました:
_python -m timeit --setup 'import subprocess; p = subprocess.Popen(["ssh", "user@Host", "cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0)' 'p.stdin.write(b"z"); assert p.stdout.read(1) == b"z"'
_
どこ
_python -m timeit
_はtimeit
Pythonモジュールを実行します。
_-s/--setup
_オプションは、各繰り返しの前に実行するステートメントをtimeit
に指示します。
subprocess.Popen(["ssh", "user@Host", "cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0)
はssh
を起動します-ホストでcat
を実行します-子/サブプロセスとして、そのIOストリームをPythonにリダイレクトしますファイルのようなオブジェクト。 _bufsize=0
_は、IOがバッファリングされないようにします。これにより、IO待機が発生する可能性があります。
そして各ループについて:p.stdin.write(b"z")
は、1バイトを子に書き込みます(次に、sshを介してcat
に書き込みます)。p.stdout.read(1)
は、子から1バイトを読み取ります。その周りのアサーションは、そのバイトがあなたが書き込んだバイトと同じかどうかをテストします。
同じことを要約しますが、名前付きパイプ(mkfifo
)の作成をスキップします。実行するループが多いほど、各ループが高速になることに気づきました。 _-n/--number
_を使用して制御する:_python -m timeit --number 50 ...
_
私のアイデアは、これにターミナルクエリシーケンスを使用することでした。利点は、これをサーバーで単に実行できることです。欠点は、接続の待ち時間だけでなく、端末の待ち時間も測定することです(ただし、通常、ネットワークの遅延と比較して、端末の応答時間はごくわずかです)。これは、全体的なレイテンシであなたが意味するものです
#!/usr/bin/env python3
# Measure terminal latency (round-trip time) using "Query device code" command
from sys import stdin, stdout
import tty, termios, time
oldtty = termios.tcgetattr(stdin)
try:
tty.setcbreak(stdout)
runs = 10
results = []
for _ in range(runs):
stdout.write("\x1b[c")
stdout.flush()
t1 = time.time()
ch = stdin.read(1)
assert(ch == '\x1b')
t2 = time.time()
while stdin.read(1) != 'c': # swallow rest of report
continue
latency = (t2 - t1) * 1000
print('%.1fms' % (latency))
results.append(latency)
print()
print('avg: %.1fms min: %.1fms max: %.1fms' % (
sum(results) / runs,
min(results),
max(results)))
finally:
termios.tcsetattr(stdin, termios.TCSADRAIN, oldtty)
(これは「デバイスコードクエリ」を使用します。これまでに試したすべての端末:xterm、alacritty、gnome-terminalです。MacOSでは自分で試すことはできません。このため、YMMVを使用しない場合は、別のリクエストターミナルに関するいくつかの情報を調査することは機能する可能性があります http://www.termsys.demon.co.uk/vtansi.htm を参照してください