macOS ssh upload の、呪い…

基盤:クラウドのサーバにscpでファイルをアップロードするのが異常に遅いのが気になっていました。

開発:なんか1MB/sくらいしか出ないとか。

基盤:で、どうやらそれは macOS 固有の問題なのでは無いかということがわかりました。まず、上りは1.1MB/s。

基盤:一方、下りは11MB/s。

基盤:これは、途中の回線が非対称なのか、サーバ側でチョークされてるのかと思っていたのですが、実はFTPなら両方とも11MB/s以上でることがわかりました。FTPサーバはDeleGate、クライアントはncftpです。

基盤:それでもしやと思い、Parallels上のUbuntuからも試してみました。

開発:対称ですね。

基盤:いったい何やってんですかね?iMacでも同様です。

開発:まあ、tcpdump してみればわかるでしょうけど。

基盤:めんどうくさいんですよね。

社長:統計情報だけ見れればよいのですけどね。

開発:それもこれも、macOSのアクティビティモニタがおもちゃのタコだからいけない。

社長:それをどうにかしようというのが4月の予定でしたが…

基盤:/etc/ssh/ssh_config とか ~/.ssh/ssh_config とか特になにも設定してないようです。

基盤:ローカルなホストとでは、上り下り対称です。

開発: 1Gbps使い切ってますね。

社長:ひょっとしてsocketのバッファが小さいとかじゃないですかね。送受信でサイズが非対称なのはよくあることです。昔は数十KBの世界でしたが、最近では1MBなんていう設定も見ます。

開発:そういうシンプルな話ですかね… とりあえずDeleGateのtcprelayを通してみますか。まずDeleGateのソケットバッファって…

社長:I/Oともに131072バイト、つまり 0x20000バイトにしてますね。10年前では常識的なサイズだったようにも思います。

開発:ではこれで、idg9 -fv -P9022 SERVER=teprelay://jp1:22とかして、ローカルの9022ポートをdg9サーバのSSH/22につなぐ。でもって scp …

基盤:驚愕の25倍速

開発:なぜか送信だけ速くなりましたね。もういっちょトライ。

社長:送信パケット自体は60MB/s出てるようですね。いや、これってマシンローカルのパケットもカウントしてるのかな。だとすると値が2倍に出ますが。

開発:DeleGateでソケットバッファサイズを指定するのってどうするんでしたっけ。

社長:SOCKOPTとかなんとか… マニュアルを見て下さい。

開発:… これですね

社長:ああ、キオスクのだじゃれだったのを覚えています。

開発:-Fver には反映されないような。まあ、1MBにしてみますか。-vd SOCKOPT=buffsize:1024kic+1024kos を添加… DeleGateのログは…

基盤:拡張されてますね。

基盤:劇的には変わらないですね。

開発:いや立ち上がりは劇的なんで、どっかで自動的に抑制するアルゴリズムが働いてるんじゃないですかね。250MBではどうか。

社長:まあ、2割程度の変動はあると。

開発:でたとえばバッファサイズを8KBにすると、1MB/sになります。

基盤:SSH自体が何か動的な制御をしている可能性もありますよね。

社長:しかし、TCPは立ち上がり時にバッファサイズを自動調整するのは知ってますが、全速巡航の時に何かするとは思えないんです。そこはまた何かのチョーク的なものが働いているのかも。

開発:この場合はDeleGateというユーザプロセスがバッファ機能を果たしていて、マルチコアだからパイプラインが効くということかと思いますが、そもそもscpというかsshのソケットバッファを大きくすればよいのでは無いかと思いますね。オプションであるんですかね?

社長:ですが、この問題はssh/scpに限らないわけです。ソケットバッファのサイズを前時代のまま放置しているOSとかアプリとかライブラリっていくらでもあるのかなと。というか、ソケットバッファだけでなく、アプリのI/Oバッファが小さい場合も、システムコールは増えるし。

開発:対処法はこういうところですかね。

  • カーネル内のバッファサイズサイズの設定
  • アプリ(ユーザプログラム)のバッファサイズの設定
  • TCP中継サーバ(バッファリング・圧縮、明示的 / 透明)

社長:アプリでやる場合には、send / recv あたりを動的ライブラリでラップするのが良さそうです。

基盤:これはひょっとして、Macのシステム環境設定にあるのでは… Network > Advanced … それっぽいのは無いですね。

開発:あまり全域に影響が及ぶ設定だと、リソースが無駄になるとか、予測不能な副作用もあるんでしょうね。だから「遠隔との大規模ファイル転送」にTCPを使う、という場合にだけ適用できるようにする、自動判別もしくは明示指定、というのが良いのかなと思います。

社長:うーん、タイムスリッパでやったように動的ライブラリではできそうだけど、トランスペアレントプロキシ方式が面白そうです。これだと、既存のプログラムには何の影響も与えない。パイプライン動作とか、対向で使えば圧縮とかもできそう。この線を試してみたいですね。

経理:先程の固定電話は、鹿児島から黒酢ドリンクのセールスでした。今あちらでは気温が35度に達しているそうで、大変ですね。種子島のとっぴーの話とかで盛り上がっちゃいました。

基盤:随分長電話してましたが、長距離電話って今は安いんですかね。ネット電話?

社長:昼食行ってきます。

* * *

社長:メロンソーダを飲みながら帰社であります。

開発:夏休みですね。

社長:いやー、外はまさに真夏。でも社内は涼しいですね。

基盤:ただいまの室温、31.6度。

経理:心頭滅却すれば火もまた涼し。

基盤:気休めにベランダに打ち水しておきます。

社長:それで今日は初めてのラーメンやさんに入りました。真鯛のスープ+えびすの小瓶。あれはハマりでしたね。

社長:それで食べながら考えたんですが、やはりトランスペアレントプロキシ方式はsuにならないと使えないのが嫌だなと。実現性がOSにも依存するし。それで、accept と connect を動的ライブラリでフックして、socket pairで中継用のスレッドかプロセスを挿入するのが良いかなと。

基盤:気化熱作戦、効かないですね。室温0.1度上昇。

開発:水道の水をラジエータに通すっていうのはどうですかね。室温よりだいぶ低いでしょう。

基盤:東京都の水道水だと8月でも27〜28度くらいのようです。

社長:井戸水があれば強力なのに。あれなら、15度くらいですよね。

* * *

開発:しかしとりあえずscpが高速化できればいいや的なら、DeleGateみたいな中継器を立てて、そこにsshすれば良いので、今でも十分なわけです。ただちょっと使い勝手が悪いのは、複数のサーバを相手にしている場合に、ホスト名とかアドレスを変えるたびにいちいちknown_hostsがー、って言ってくるところです。何なんですかね?

基盤:ユーザの鍵で認証しているのに、その上ホストの認証とか必要なんですかね?ユーザの鍵を盗まれた時点で詰んでるように思うんですが。

社長:鍵認証じゃない場合に必要なんじゃないですかね?あとはログイン後にsuとかでパスワードを入れる場合とか。

開発:現在のセッションのアカウントは認証されてるわけだから、その大元との間でワンタイムパスワードみたいのを発行して、それを中間で入れされる、で良いように思いますね。

社長:まあ、ひとつのテキスト端末で全部やりとりしてるって想定でしょうからね。telnet ならout-of-band的に、端末には表示されないメッセージをエンドツーエンドで交換して、クライアント側のウィンドウなりをポップアップするとかできそうですが。SSHはそういうのできるんですかね?

基盤:パスワードをユーザの鍵で暗号化してloginに渡すのでも良い気がします。

開発:そもそも「ホストにログインする」というホストって何?ログインて何?とも思うのです。まあたしかにsshはコマンドインタプリタとしてホストというものにログインする形態のソフトだから、そういう概念はあるんだと思いますが。リモートにコマンドを送るだけとか、とにかく端末からコマンドshellとか使わない場合も多いわけです。scp とかトンネルとか。

* * *

開発:いやあ、openssh のビルドでつまづいて懲りました。が、わかったことは、scpでのアップロードが遅くなったのは、openssh-7.8からだということです。

開発:Catalina 10.15.6 の ssh は 8.1p1です。

開発:一方 Ubuntu18.04 の ssh は 7.6 だったのです。

社長:OpenSSLの版の影響は無いですか?

開発:同じ OpenSSL 1.0.1l での比較です。

開発:Lunuxでも状況は同じでした。

開発:ただよくわからないのは、openssh のコードを見ても、ソケットバッファのサイズをいじってないことです。となると、バッファがうまる前にソケットをflushというかpushして細切れパケットを発生させているのかも知れません。送信の間にコンテクストスイッチみたいな遅延が入ってるとか。

社長:うーむ、面白いですね。diff を見るのが楽しみです。ちょっとひとやすみしましょう。飲んできます。

— 2020-0804 SatoxITS