続Gshell

開発:さて、UDPでデータ転送の件は一段落したので、gshellに戻りたいとおもいます。

基盤:というかさっきから扇風機の風が生暖かいと思ったら、室内が32.6度に達しています。

社長:この扇風機がなかったら我々は終わっていますね。ありがたいことです。

経理:3万円の扇風機… 100日間使って一日300円、1000日使っても一日30円。

基盤:10年は使わないと割にあわないですね。

社長:エアコンを平均500W一日24時間30日回し続けたら、360kWh。25円/kWhだとすれば9,000円/月です。実際以前夏場はそれくらいかそれ以上の料金上積みでした。まあそれでも、飲み代2回分より安いわけで、気にしてなかったんです。

経理:会社の経費の基準は飲み代ではないですからね。

基盤:今はアマゾンセール$5がコスト比較原器です。

開発:最近はでんこ家計簿が超お楽しみコンテンツになりましたが、もう200W程度で下限で安定してしまっていて面白くなくなりました。

社長:200Wって、ちょっとしたソーラーパネルでできちゃいますよね。日中はそれでいけちゃいそうな気もしますが。

基盤:アマゾンで見ると、パネル自体は100Wで1万円というところですね。大きさは1m x 50cm くらいので扱いやすいかなと。

社長:うーん、ここはなまじヒサシが深いですからねぇ。屋上におかせてもらえると良いのですが…

開発:でも、元が取れるとかどうかではなくて、遊びとしては面白いですよね。そのためにはベランダに置いたほうが良いと思います。

社長:一応災害時への備えとかにもなりますしね。

* * *

開発:まずは gsh の現状版。v0.0.4です。

開発:現在574行。

基盤:Cで書いている部分が700行を超えてますが。

開発:それはshell自体の機能というより個別のコマンドです。あと、システムコール周りとか、Cなら簡単に書ける部分も多い。

社長:全部Goで書いたほうが移植性は良いと思いますが。

開発:我々はUnixとWindows以外への移植性を考える必要は無いと思います。DeleGateはCで書かれましたが、Windows でも LinuxでもMacOSでもBSDでも、どこでも動きますよね。使っている外部のライブラリはOpenSSLとZlibだけで、しかも動的リンクのオプショナル。問題ないと思います。

社長:まあ、Cプログラムのビルド環境がデフォでは無い場合もあるし、バイナリ配布が必要になりますね。

開発:DLLで配れば良いのかなと思います。

基盤:しかし、コマンドライン入力部分をCで書いているのはユニークかなと。

開発:tty の処理はもう何十年前からCで書いてなれてますし。要はttyというプロセスとgshellで通信するのが、端末も遠隔に出来て良いのではないかと思うわけです。

社長:ttyとネットワークで繋がるということは、要はリモートシェルになるわけですね。

開発:リモートであるとかローカルであるとかは見えなくなると思います。あるいは、一つの端末を複数のshellの間でattach/detachする。gshell自体はずっとマシンの中で生き続けていて、それにつなぐだけです。ログインに時間がかるような事もありません。

社長:ずっと状態が残っているのは便利ですね。

基盤:一種の仮想マシンのような状態なわけですね。

開発:gshellというのは基本は永続的なサービスとして生きていて、thin client的なクライアント、例えばtelnetから接続する感じかなと思います。

社長:複数同時に動いているgshellの間のネットワークを作って、横方向にも協調させると良いですね。それ自体が、アプリケーションレベルのVPNのような世界を作る。

開発:あとはファイル空間ですね。仲間のgshellが見ているファイルシステムを他のgshellでも見える。これは、NFSをgshellのネットワークで中継すれば良いかなと思います。実際、何でもできちゃうログインをしたいわけではなくて、単にそのホストにあるファイルをみたいだけということが多いです。だから、ログイン的なセッションを張っている間だけ、互いのファイルがマウントされて見えるようなのが良いかなと思いますね。便利だし、安全性の面でも。まあ要するにプライベートな automount 的な。

基盤:unfs3に出会う前は、open/read/write/close といったファイル関係のシステムコールを動的ライブラリで置き換えるって話でしたよね。

開発:その線も捨ててはいません。適材適所かなと。

社長:Gshellにtelnetで接続する様を是非見てみたいです。それ、最優先で。

基盤:macOSってtelnet無いんですよね。インストールしないと… えっと… brew install telnet。15秒でインストール完了です。

開発:ええええええええ!ずっと不便だと思いながら耐えてきたのに…

会社:もう身体にしみついちゃってるから、無意識に telnet って打っちゃいますよね (笑)

* * *

開発:とこで、フランクフルトにsshでログインするのに4秒以上かかるのがすごいストレスなんですが。

基盤:まあ汎用にできてるでしょうから色々ネゴしているでしょうね。1ネゴに0.5秒掛かるわけで。

社長:じゃーん。そういう時のために、私が昔作ったリモートシェルサーバはいかがでしょうか?実は昔の名残で、全ライトセール機でサーバ自体は動いているのです。あとはファイアーウォールを通してもらえれば。

基盤:ポート番号は?

社長:ごにょごにょ…

基盤:では、我社のIPアドレスからだけ、TCPを通します…

開発:しかしライトセールって、日本語のわかるスタッフ雇ってないんでしょうね。ここでもてにをはがおかしい。

社長:なにせ安くあげるのが至上命題でしょうからね。我々もその恩恵を受けている。サービス提供では人件費が一番金を食う。

基盤:はい、全ライトセール機のファイアウォールを設定しました。

社長:それでは、さっそく。えーと使い方は、ああ、単にホスト名を指定すれば良いのでした。ではログイン。

基盤:なんかさくっと入りましたね。

社長:まあ、入った後は、キー入力のエコーとかは0.5秒かかるのはどうにもならないですが。RTT 0.25秒ですから。

開発:ちょっとログインの所要時間を測ってみましょう。

開発:4秒は耐え難いですが、1秒はまあありですね。1秒ということは、認証に2往復しているんですね?

社長:yysh に -fv オプションを付けると、HTTP風なメッセージのやりとりが見えますよ。まあ繋がると同時に両側から情報を出せばもう一段高速化はするかと思います。

基盤:普通に使えるんですか?

社長:昔はsshサーバとかほとんど無かったし、これで何年も暮らしてました。X Windowも中継しますよ。何段でも多段中継して。

基盤:TCPコネクションは一本なんですか?

社長:そうです。YYMUXという自作のマルチプレクサーです。

開発:暗号化は?

社長:鍵交換は自作のDiffie-Hellmanです。当時はOpenSSLがまだ広くは普及してませんでしたしね。というかSSLeayでしたけど。暗号化はCredhyというこれも自作のストリーム暗号アルゴリズム(^-^)

開発:鉄壁ですねw

社長:では思い出しがてら、デモをば… ドイツ支所に居るxeyesでつくば本社内を監視させてみます。

フランクフルトからつくば本社内を監視するxeyes

基盤:おおぅ。一応カクカク追随しますね。

社長:まあ、RTTが250msなもので。

開発:なんにしても長距離でキーのエコーとか遅延がどうにもならないですから、エディタ的なインタラクティブなものは手元で動かして、ファイルシステムだけ遠方のをマウントするという事になるでしょうね。

社長:せっかくなので、我社世界5拠点を数珠つなぎに一周してみたいですね。

基盤:では各サイトのファイアウォールをそのように設定…

社長:では、東京>オレゴン>フランクフルト>ムンバイ>シドニーを一巡りしてみます。えい。

基盤:3秒で帰ってきました。なかなかですね。

開発:これって、通過したところでそれぞれにトンネルを作りますよね。一本のシリアルバス状のトンネルを作ると、通過した地点の間のVPN的なものができると便利かなと思います。

基盤:それって乗り合いバスというより、乗り合いタクシーみたいですね。

社長:面白いけど、隣以外と通信する時にいちいち多段中継されるのでは、遅延が厳しい気はしますね。何かスター状のバスもはらないと…

開発:たぶん、リフレクタ的なバスをどこかに作って、そこに対するアクセス許可をシリアルバスで順次申し伝えするって感じですかね。

社長:アクセス権の面でも、そいつがどこからどうやって来た馬の骨かがわかると、面白い管理ができるかも知れません。

開発:ドメイン名システムができる前のUUCPのパスアドレスを思い出します。

* * *

長距離UDPで驚速データ転送を実現

開発:そもそもshellを作ろうと思い立ったのは昨日の朝、UDPでならどの程度のデータ転送速度が実現できるか興味を持ったためです。でついつい、Cでゼロからプログラムを書き始めてしまったのですが、しばらくして、いやいやこんな力仕事的な書き方はもう卒業すべきだと思い、Goに立ち返ったのでした。

開発:で、ソケットを作ったり繋いだりするのはGoのパッケージを使えば簡単に書けるわけです。まあ、ライブラリがあればどんな言語だって簡単ですけど。しかも、Goで使うべき関数を間違えてしばらく戸惑いました。システム関係のパッケージのドキュメントはどうも完成度が低い気がします。まあともかく、やってみた結果がこれです。

基盤:2.27GB/s!

開発:もちろんUDPですから、データは取りこぼすわけです。ですが、同一マシン内で、マシンの負荷が軽ければ、ほぼ受け取れます。この例では 99.7%は受け取れています。

基盤:このMacMiniがこれまで生きてきて一番高速なネットワーク転送です。

社長:使用しているメモリ2.7GHzですからね。まあおそらく64bit、8バイト/クロックでアクセスできるんでしょうけど。いや、32ビットかな?

開発:32ビット4バイトだったとすると4 x 2.7 で 10.8GB/s、64ビット8バイトだとすると21.6GB/s は出るはずですね。

基盤:172.8Gbps。

社長:メモリのコピーでは読んで書くから、その半分になる。だからメモリのコピーは最速で10GB/sと思います。

開発:ただ、CPUの命令ループでコピーする場合、1ワードのコピーにCPUクロックが複数かかりますね。ソースとディスティネーションのポインタレジスタの更新、終了判定、あとはロードとストアと、結局8バイトのコピーに8クロックくらいかかると思うんです。簡単なテストプログラムを書いて測りました。volatile にした 100MBのバッファの間をでコピーを10回繰り返すというものです。

基盤:理論値の10GB/s出てますね。

社長:ユーザからDMAは使えないんですかね?

開発:さあ。このmemcpyの値は、異常に速かったり遅かったりします。デュアルポートメモリでも無いでしょうに18GB/s出ているのも謎です。他のCPUループでの実装はほぼ安定していますので、ひょっとしてDMAを使っているのかも知れません。デバイスとして使えるんでしょうか。システムコールで叩いてるんでしょうか?

基盤:通信経由のコピーがプロセス内でのメモリーメモリコピーと同等というのはびっくりですね。

開発:それも実際にはDMAによるメモリーメモリコピーに帰着させてるんじゃないかとは思いますけどね。他のマシンへの転送では、数マイクロ秒間隔を開けてやらないと、OSのバッファがいっぱいになってエラーが出るのですが、同一マシン内だとそれが出ないんです。

社長:自分自身に送信してコピーすると高速化したりするかもですねw

* * *

開発:それで、次はTCPではどうなのかといことになります。やってみた結果がこれ。

基盤:ネットが6.23Gbpsに到達しております!

開発:このMacMiniは、外に対しては1GB/sでしか繋がりませんが、内部的には違う話ですね。プロセス間での通信は、プロセス内部でのメモリのコピーと同等の性能が出ていると見えます。

社長:TCPのほうが速いんですね。

開発:UDPだと固定長パケットで、8KBを超えると起こられてしまうわけです。だから送信の回数、OSとの通信が多くなります。一方TCPではそういう制約は無いですから、でっかいバッファのありかをどーんとOSに教えてやって任せればよいわけです。200KB程度のサイズまでは、サイズが大きいほど速くなります。

基盤:ただこれは、同一マシン内での通信の特殊状況なんでしょうね。

開発:そうですね。ping への RTT が 0.05ms とかいう世界です。これが、隣のマシンになると 0.5ms程度はどうしてもかかる。さらにWANに出ると速くても5ms程度はかかる。アジア近隣で50ms、アメリカまで行くと130ms、ヨーロッパまで行くと250msになってしまうわけです。相手の受信確認を頻繁に行うTCPではこれは、まるで別の世界になってしまいます。

* * *

開発:されそれで、RTT 0.5ms程度の隣のマシンとの転送ですが、sendのサイズは1500バイトで十分に1Gbpsを使い切ることがわかりました。

開発:一方UDPの成績は芳しくありません。どうも性能が出ない…

* * *

開発:えーと、調整をした結果、まずまずの性能に落ち着きました。

受信側
送信側

開発:ペイロードぶんのスピードとして TCPでは 940Mbps出ていますので、理論上の最高性能かなと思います。一方UDPでは 880Mbps程度。連続して送るとシステムのバッファが溢れてしまうので、4マイクロ間隔で1430Bを送っています。これだと、バッファがいっぱいだよエラーが出ませんし、受け側もほぼ100%受け取れます。これ以上間隔を短くすると、送り側としてはTCP並の速度で送れますが、受け側がボロボロになります。

開発:ああ、でも3usなら送信側が再試行すれば100%受け取られますね。

3us間隔送信
2us間隔送信
1us間隔送信

無間隔送信

基盤:ぼろぼろですねw

社長:要するにLANというかレイテンシーがサブミリ秒の近接したノード間でUDPを使うメリットは無いということですね。

開発:そう思います。で、問題はレイテンシーが大きい時はどうか、ということで、本題になります。なお、この実験は電力を約60W食うことが観測されています(笑)

* * *

開発:まあこれは実は最初にやって結果はわかっていまして、比較のためにマシン内や近接マシンで試すのに時間をとられてしまいました。

開発:ではまずは最果ての地、ドイツフランクフルト支所。RTT 250ms 超です。ここはscpのアップロードで1MB/sしか出ないことがわかっています。このベンチマークでもTCPでのデータ送信は同様な結果になります。

基盤:しかもスピードが時々刻々かわっている。ネットの状況に左右されてるんでしょうね。遠隔との通信の速度は、非常に不安定であることは実感としてわかっています。

開発:そしていよいよ、UDPではどうか。

基盤:50MB/s で届いていますね!50倍速

開発:まあ、半分落ちてますけどね。

社長:といいますか、我社から社外に向けて実際にギガビットでデータを送出したのはこれが初めてですね。

開発:それでこの数値は、相手がドイツでも東京でも大差無いんですよ。つまり、うちのインターネットは、上りは500Mbpsしか出ないのではないかという気もします。

社長:ライトセール以外の相手にためしてみたいところですが。CPU負荷的に厳しいとか。

開発:全般的には余裕ですね。30%食うことはないです。なにせデータを受けるだけで何も処理してませんし。

開発:たとえばライトセール東京にある我社ネームサーバ。

開発:もともとパケットがロスするのは織り込み済みですから、到達してないパケットのマップを返してもらって再送すればよいわけですが、ではどのくらいの速度までロスが起こらないかをためしてみす。… … 6.28MiB/s、50Mbps までは大丈夫っぽいですね。

開発:161マイクロ秒間隔での送信です。

社長:刻みましたねw

開発:普通のデータは1ビットでも落ちたらいけませんが、画像とかはとりあえず届いたものから表示するとか、ありますよね。動画だったらなんだか画質が落ちるとか。

社長:これはそもそも、差分だけ送るという方法に相性が良いですね。rsync とはちょっと違う方向性を考えると面白いかも。

基盤:ところで我社の$5ライトセールは2TB/月という制約ですが、どういうふうにリミットしているんでしょう?もうけっこう上限のような。

開発:ドイツ支部は暇だし死んでも大丈夫ですw でも、テスト用のインスタンスを作ってやってみますかね。

経理:まさか、上限を超えたぶんは従量課金になるとかではないですよね…

— 2020-0809 SatoxITS

そうだ、Shellを作ろう

開発:プログラマとして生まれたからにはやはり、一度は自分のshellを作ってみたいものだと思うわけです。

基盤:どういう生まれ方をしたんですか。

開発:私がCプログラマになったころにはまだ、Unix V6でしたから、V6のshellしかなかったんです。ヒストリを参照するのにいちいち !なんとかを入れないといけない。面倒なのでカーソルで昔のヒストリに戻れるようなのを作りましたよ。それとか、プログラムのPATH同様のデータのPATHを定義して、参照したデータファイルをそのPATHで探索して開くようなこともしました。ファイル名を入れるとそのディレクトリにジャンプするとか。

開発:最近はzshやsshに、大いに刺激されました。コマンドラインシェルは不滅だなという気もしました。ですが、コーディングを見るとまあ、昔ながらのCなわけです。それはそれで好きなわけですが、今はもうそういう時代では無いのではないかなという気もするわけです。

開発:shell の重要な役割は、実行するプログラムの外部環境を整えて提供することだと思うんです。環境としてはまず、ファイルディスクリプタで与えたり、動的ライブラリとして与えたりするもの。あるいはファイルシステムの可視性を与えるかも知れない。実行のタイミングを与えるかも知れない。

開発:Unixがくれた重要な概念として標準入出力というのがあるわけです。これはコマンドのパイプラインを筆頭として、プログラムを部品化して再利用性を高めるのに大いに有益でした。そのうえ、入出力をどこにつなぐかというコーディングを各プログラムからなくすことができた。まあ必ずしもそうはなっていませんが。

開発:例えば、shellが開いてファイルディスクリプタとしてプログラムに与えて上げられるのはふつう、ローカルファイルかパイプだけなわけです。ですが、今やもちろん、リソースもさまざまだし、つなぐのだってパイプとは限らない。

開発:あるいは、コマンド引数というものを各プログラムが解釈するからてんでばらばらになったりするわけですが、shell が標準的な引数フォーマットを解釈して前処理して、プログラムは解釈結果だけを利用するようにすれば、もっと統一性がとれるし、プログラムのコーディングも省けるはずです。

社長:で実装の方針は?

開発:今から作るならやはりGoベースだと思うんです。豊富なパッケージを組み込みコマンドとして使えるし。

基盤:そういうのって既にあるんじゃないですかね。

開発:いや、既にあるとか関係ないです。これは、自分なりのshellを作ってみたいという欲求に突き動かされているものです。そして、実際自分なりに作って改良して行くと、既存のものには無かった何かが、必ず生まれるものです。無知や誤解はオリジナリティの父になります。だからこの件については、既存のものがあるか調べ物はしません。

開発:第一次トライアルは3日程度のスプリントで考えたいと思います。

社長:何という名前にしますか。

開発:まあとりあえず安直に、gsh ですかね。

社長:承認。

* * *

開発:というわけで、第1版ができました。こんなかんじです。

開発:機能的には、golang の eval が出来るようにした点と、コマンドを実行するごとに実行時間を自動表示する点が特長です。実装上は、fork して exec する方法を調べるのに少し手間取りました。現在のコードはこんな感じ。

社長:内部コマンドも実行時間を表示してくれると良いですね。

基盤:システムコールナマ呼び出しですか…

開発:Goの皮をかぶってると自由が効かないんですよ。データ構造的には Goの機能を活用させてもらいますが、外部とのやりとりというか結線は、ナマでやろうと思います。

社長:良い感じですね。ちょっと食事に行ってきます。

* * *

社長:帰りました。またえびすの小瓶のラーメンやでした。

経理:大変な事になりました。これを見て下さい。

経理:左が一昨日の電気使用量。ほぼ200Wべたです。右が昨日。零時頃にエアコンをつけて8時に切り、ついでに各種の無駄機器の電源を切りました。

社長:劇的ビフォー・アフター。

基盤:これ、スケールが変わっちゃってますね。そろえるとこうなります。

開発:つまり一昨日まで200Wだったのが、昨日深夜から朝まで400Wになり、その後100Wになった。

基盤:ただ不思議なのは、UPSの電力計は常時150Wを超えていますから、100W刻みのてぷこでんこ計では200と100が交互になりそうに思うんですが、このグラフではほぼ100Wで推移していることです。

社長:まあ、これが逆だったら問題ですけどね。しかしうちって100Wで維持できちゃう会社なんだなあ。

経理:こうなるともう、基本料金が気になってきますね。契約の容量を下げましょうか?

社長:まあ話としては面白いですが… いざという時のこともあるし。他の方面に残っている巨悪から片付けたほうが良さそうです。

開発:あれ?でんこ計の縦軸ってkWhですね。一つの棒は30分毎。つまり30分に0.1kWhてことで、1時間平均にすると0.2kWh、つまり平均消費電力200Wということなのでは?

社長:あ。なるほど… それなら計算が合います。

基盤:なんにしても一昨日まで平均400W使ってたのを、昨日から200Wに削減できたと。照明を落としたり、無駄に電源に電源ONのまま待機していたテレビやオーディオを切った効果でしょうか。何ヶ月、というか何年も無駄に200W食い続けてたなんて、恐ろし過ぎる…

基盤:ああ、それはそうと、このPoerMeter、結局 macOS版はしょっちゅ接続不能になってしまうので、Lenovoで動かすことにしました。いまのところ朝からずっと快調です。

* * *

開発:ふぁ。あ。ぁあ。あー、よく寝た。

社長:よく規則正しい生活をって言いますが、寝たい時に寝て食べたい時に食べる。どっちが身体にいいんでしょうね?

基盤:まあ無理に寝る必要が無いので、不眠症というものはこの生活スタイルには存在しないですね。

* * *

開発:第2版ができました。こんな感じです。

開発:今回は repeat というコマンドを入れました(4>)。nop というコマンドを1,000,000 回実行して所要8.6ms、つまり一回あたり8.6ns であることがわかります。

社長:さすが3GHzのCPUですね。私がこないだまで触ってた100MHzのARMとはえらい違いです(^-^)

開発:それと、lets.go というファイルを “go run lets.go” なしで、単に lets で実行できるようにしました(6>)。

開発:あと、外部コマンドの入力ファイルや出力ファイルを -i ifile -o ofile command のように指定できるようにしました。まあ通常のshellなら、command < ifile > ofile なところです。

開発:全般的に、とにかくシンプルに左から実行して行くという型式です。

社長:まあ中置記法は実は人間にも優しくないという事もあるかも知れません。

開発:実行の順序を変えるには、その先に実行するコマンドをプッシュできると良いのかなと思います。

社長:コマンドや実行結果をスタックに積んでポーランド記法的に結果の掛け合わせができると面白いでしょうね。ある意味 repeat は、積んだり降ろしたりの例ですね。

開発:ということで、現在のコードはこんな感じです。

社長:今300行ぐらいですね。どのくらいで落ち着きそうですか?

開発:まあ1000行あれば、そこそこshellっぽいものになるかなと。3000行くらいで、けっこう実用的なものになる気がします。Goのパッケージに部品が豊富にあるので、いかに活用できるかかなと思います。

* * *

ブラウザの色好み

社長:ただいま帰りました。

経理:酒臭いですね。

社長:今日は12LSUを投じて我社枢軸の精神衛生および創造性に多大の寄与をもたらす、… というか、部屋がやけに暗いというか。

経理:照明を絞ってみました。測るのが難しいのですが、数ワット削れている可能性があります。

開発:蛍の光窓の雪のような。

基盤:ホタルの発光は有機ELの元祖なんでしょうけど、普通窓の雪は発光しないですよね。ヤバいものが混じってなければ。

社長:君はチェレンコフの光を見たことがあるか。

開発:融解の熱が何らかの作用で光に転じているとか。

社長:常温核融合もびっくりですが。新しい触媒?まあ生体なら有り得るんでしょうね。雪の結晶の形をした微生物だったとか。

基盤:スクリーンセーバを合成で作るなら、ホタルが飛び交ってるような風景を作って欲しいですね。

開発:線香花火とか。

社長:おばけ屋敷とか。

経理:三流紙に書かれそうですね。社内はまるでお化け屋敷のようだった(捜査員談)

広報:メディアを呼んで何かプレス発表してみたいです。

社長:うーむ、ブラックライトは清涼感を醸すのに良いかも知れないですね。

社長:ああそれで飲んでる時に、前々から気になっているFirefoxの色使いについて、考えたのですが。

社長:あれっていわゆるRGBモデルじゃなくて、アドビモデルとかいうやつなんじゃないだろうかと。

基盤:PDF臭いですね。セピアっぽい。

開発:モニタで見るようには出来てない?

社長:主要5+1ブラウザを並べてみます。

社長:まあ、ひと目見て右下がFirefoxだとわかるわけです。色で。

基盤:うーん、その他も、どれが何のブラウザかわかるようになりましたw

開発:というか、ブラウザごとにアイコンはあるんで、それを右下あたりに主張してもいいんじゃないですかね。ユーザの設定でもいいですけど。

社長:画像の圧縮のアルゴリズムというかポリシーはCSSとかでも既定されていると思うんですが、たぶん細部は実装依存。で、Firefox以外はOSが提供しているライブラリか、Chromiumの共通ライブラリを使ってるんじゃないだろうかと思うわけです。

開発:なんにしても印刷用のヘッダのバナーは、ブラウザの生成に任せるのではなくて、明示的に提供してあげたほうがよいでしょうね。著作者もびっくりな色で印刷されたら、権利問題じゃないかと。

社長:PDF といっても、画面で見る時と印刷する場合がありますから、用途を選択できると良いと思います。

基盤:自動変換できるんじゃないでしょうか?

社長:それはそうと、今日は帰社して快適だなと思ったら、私の体調のせいではなくて室温が29度を切っていますね。

経理:ずっと窓を締め切ってエアコンをつけっぱなしにしていると気が付かないですよね。

開発:今日は洗濯日和とか気象予報士が言ってますけど、今日はこういう風向きだから、窓を開けて自然の風を楽しむ日和ですみたいな事を言ってほしいですね。言ってるのかも知れないけど。

社長:花粉予報はみっちりやってますよね。

基盤:まあ民放とかでは公共の電波でくだらない星占いとか流してますけどねw

社長:私もいい年まで血液型性格判断を受け入れてた口だし(笑)。民放はエンタメなんだからいいんじゃないですか。スポーツの中継しか見ないけど。

— 2020-0807 SatoxITS

祝30000カウント

基盤:早めに祝賀会場を設営しました。

開発:何をカウントしてるんだかわからないんですけどねw

社長:ああそれで、記念写真に限らないですが、情報にはかならずその発生日付が必要だと思うんです。

開発:前回の20000の時には間に合いませんでしたが、今日はできそうです。ネームサーバ移転の時に書いたPHPの関数をショートコードで参照すればよいかと。

開発:ああ、reqTimeというショートコードを作ってますね。ではこれをそのまま使用します。ブロックの中でならこう。

1596995512

社長:おっと、ナマのunixtimeなんですね。

開発:とりあえず。というか、ヒト可読性が低いほうが良いこともあるかと。で、これをサードバーに入れるには… あれ? とうか、このカウンターをブロックで埋め込むショートコードはわかっているのです。表示オプションとか全部デフォルトで良いなら単に、[ ] の中に ads-wpsitecount と書けば良い。するとこうなる。

基盤:おそろしげなデフォルト表示ですね。

開発:それで今気づいたのですが、普通に段落ブロックの中にそう書いても埋め込まれるんですね。こんなふうに( 31754

基盤:ならなんでショートコードという特別なブロックが通常の段落ブロックとは別にあるんでしょうかね?

開発:さて、それではこれをサイドバーに入れるにはどうしたら良いのか。サイドバーに通常のブロックが入れられるのか… ダメ元で拡張HTMLに入れると、まんま出てきてしまいます。

開発:拡張HTML以外にはユーザが手書きできるような部品が無いですね…

基盤:その「テキスト」ってなんですかね。プレインテキストとは思えないんですが。

開発:あ。なるほど。

開発:では「テキスト」を追加。

開発:「ビジュアル」表示にしても、ショートコードのままですね。いわゆるプレビューだと思うんですが。

基盤:とりあえず「公開」して閲覧してみては。

開発:やってみますが…

開発:おっと出ました (^-^)/ WordPressのプレビューっていうのはこういうところが不完全ですね。しかしこれが「テキスト」というのはねえ…

社長:WordPress な人にとっては空気のようにテキストなんでしょうね。

開発:こっちのほうがよほど「拡張HTML」の名にふさわしいとおもうんですが。で、拡張HTMLの中でショートコードを呼べるかですが… short code in extended html で検索… ありますね。

開発:どうも <?php echo do_shortcode(‘[ショートコード]’); ?> という風に書けちゃうみたいですね。やってみましょう。

開発:これでどうかな?「

基盤:空っぽですね。

開発:何か権限の設定とかが必要なんですかね?

社長:普通のテキストの中にしろ拡張HTMLの中にしろ、PHPがナマで掛けちゃうならすごい強力ですね。いちいち functions.php とかいじらなくて良い。

開発:インラインCSSのノリですよね。まあそれはお楽しみとして。asctime 的な strftime 的なものを PHP でどう書くのかなんですが… strftime PHP で検索。そのまんまありましたw

開発:では Date という関数とショートコードを定義して読んでみますと…

[Date]

開発:いちいち大げさですねw まあ予約語なんですかね。では xDate で…

基盤:これはまた破壊的な。

開発:私のどこがいけないの〜。あれ?関数名の前に $ が付いてます。

開発:ではこれを消して xDate 召喚…

2020-08-09 17:51:52 (GMT)

基盤:出ました。でもタイムゾーンがJSTじゃないですね。

開発:ではGMTですとお断り書きをw そしてサイドバーの「テキスト」ウィジェットに貼り付け。ほい。

社長:とりあえず最小限の機能要件を満たしましたw ちょっと配置を整理しましょう。

開発:といいますか、ウィジェットとして編集するより手書きで「テキスト」に書いたほうが簡単な事がわかりましたので、カウンターもショートコードにしてしまいます。QRもロゴも近くに来てもらって… こんな配置では?

社長:位置関係的には良いかもですね。あとは隙間をどう調整するか。まあ今回はこれでも十分です。

基盤:このタイムスタンプとログを突き合わせれば、ハエあるキリ番取得者が誰だかわかりますね。でも、秒単位ではちょっと。

社長:DeleGate では %s です。

開発:うーん。無いですね。もとになる値が秒単位だからですかね。秒単位以下だと microtime() かな。

社長:私の業界では msec はミリ秒、マイクロ秒は usec ですけどね。

開発:ではそのまんま使わせていただくとしまして…

基盤:そろそろキリ番が近づいてまいりました。その時にページが Fatal error だと悲しいですね。

開発:じゃあこれ以上いじらずにその時を待ちますか。

社長:といいますか、この時刻はカウンターがカウントアップされた時のものではなくて、このページを閲覧・生成した時の値だから、やっぱりキリ番取得者の特定には使えないですね。

開発:あそうか… てことは、カウンターのウィジェットに手を入れて、カウントアップした時の時刻を記録するようにしないといけないですね。

基盤:あと11…

基盤:20000の時はあと1というところで数分かかって、キリ番を見損ねてしまいました。

開発:やはりキリ番監視ロボットというか、extension が必要ですね。

社長:まあ、カンターウィジェット自体がカウントアップした時に魚拓を取ってくれればよいのかなとも。

基盤:あと8…

基盤:あと5…

開発:数分に1つだからしびれが切れますね。

基盤:とか書いているうちにこないだは見逃したわけです。あと4… このごに及んでfunctions.phpを壊したりしないでくださいねw あと2… あと1…

基盤:30000到達しました。

社長:その時、2020年8月7日、9時34分3秒(グリニッジ標準時)、 ITS more社のサイトは30000ビュー(?)に到達しました。

基盤:まあ最後は10秒間隔くらいでリロードしてましたから、誤差は10秒以内ですね。

開発:WordPress と PHP のこともまた少し学習しました。

基盤:ではまた40000の時に。

社長:いやもう、次は100,000の時でいいかな。

基盤:記念に30003番も魚拓。

— 2020-0807 SatoxITS

短期記憶力200%増(当社比)

基盤:では、iMacのメモリを増設します。現在16GB。

基盤:で、このカニの腹、ふんどし?みたいなところを開けて増設できるはずなんですが、どうやって開けるのか… おっと、電源のジャックのところにボタンがあると。BMWのキーで押す。固い?えい。深い?えーいいっ

iMac:ぱこっ。

基盤:でこのレバーを引くと出てくると。しかしこの足が邪魔ですね。外せないんですかね?

開発:外せるくらいならモアイ状のまま配達されたりしないのでは。

基盤:でこのメモリの基板を挿すわけですが、あー足が邪魔だ。なんで左右どっちかにオフセットしないんですかね?

基盤:そもそもどっちを表にして挿せばよいのやら。

開発:まあ確率1/2ですね。外れたらその切込みで教えてくれるでしょう。

基盤:えい。

iMac:グスっ。

基盤:当たりました。いまいちガスっとカチッと感が無いですが、先人と同じ高さになりました。ではもう一枚。入れました。

基盤:で蓋を戻して。あれ、これもちょっと難解…。ケーブルを戻して、電源ON。立ち上がりました。

開発:メデタシ。

基盤:なるほど、高いメモリには基板にパーツ番号とかシリアル番号とか記録しているROMが載っているんですかね。

開発:でも製造元情報は安メモリにもありますけどね…

基盤:あれ、この「メモリのアップグレードの手順」てなんですかね?クリック。

基盤:はあ?

開発:サポート用のサーバくらいちゃんと維持してほしいものですね。

基盤:増設したメモリのせいじゃないですよね… MacMini で見てみる。

社長:まあメッセージからして、HTTPサーバの設定異常ですよね。

開発:しかし、なんともメモリがノンプレッシャーですねw

基盤:では、メモリ16GBでは2ゲストOSくらいしか同時に動かせなかったParallelsで、全開行ってみます。

基盤:6ゲストOS並列、なんともないですね。

開発:CPUもまだ余裕がありますね。要はメモリが十分にあればページフォールトとかも起こらないのでまともに動くと。

社長:いやー、ソフトの開発環境としてはもう十分×2くらいですね。素晴らしい。昼食に行きましょう。

— 2020-0806 SatoxITS

エアコン復活の日

社長:冷房の無い店で飲んできたら身体に熱がこもったような。体調が思わしくありませんです。ふぅ…

基盤:真夜中に室内32度に達してますね。風もなく… はぁ…

開発:冷房入れたらいいんじゃないですかね… ハァハァ…

経理:異議なし…(ぐったり)

基盤:では当社初の冷房運転を。えーとリモコン… というか、エアコンがエラーコードみたいのを表示して停止しています… 電源を入れ直してリセット。ああ、動き出しました。ですがなかなか冷風が出てこないですね。

開発:冷媒が抜けてるとか。冷媒師を呼ばないと。

社長:ああ、冷気を感じます。甦る感じ。

基盤:しかしなんですかねこの騒音。台所の換気扇並なんですが…

開発:古いエアコンだと効率も悪いかもですね。

* * *

基盤:室温29度まで低下。肌寒いくらいに感じますね。

開発:さて、電気代にどう出ますやら。

経理:でんこちゃんで見てみたのですが、当社は通常200Wのようです。8/6朝現在では一昨日8/4のぶんまでが見れます。

社長:みごとにフラットですね。

開発:スマートメータの割には反応が鈍いんですね。

基盤:刻みが100Wですか。

社長:ていうか、自宅内で直にでんこメータと通信したいですよね。PLCでつながらないのかな?

基盤:しかし、このメータを見ると何も活動が無いように見えますね。この会社は無人か?って感じ。

開発:季節柄、幽霊会社w

経理:えーと、動きのある日としては… 7/24(金、体育の日)とか。

開発:なんでしょうね。ブログによると、クラウドを使ってただけの日みたいですが…

基盤:30分刻みの棒が5本、つまり洗濯乾燥機の活動時間と思われます。

開発:なるほど、逆に乾燥が200Wで済んでるってのが意外に思われますが…

経理:そもそももっと前は200W以下で推移していたようです。

経理:それが 7/22 夕方からは200を切ることがなくなりました。

開発:なにがあった日ですかね。

基盤:iMacが稼働し始めた日ですね。

開発:iMacといえば、ブラウザのコンパイルでギンギンにCPUを回した7/29とかは?

経理:時折100Wの上積みが見られます。

基盤:しかしプライバシー保護を考慮してなのか、ナマデータが落とせないようだし、検索というか表示範囲選択方法も弱いようだし。もっとなんとかならないんですかね?

社長:そもそもでんき家計簿にログインできるようになるまでの認証コードの郵送とか、お金と時間もかかってますしね。

開発:これもなにかの雇用対策なんですかね…

基盤:そもそも reCAPTCHA的なのを入れてないのもどうなんだろうという気はしますね。

基盤:せっかくなのでフィリップス君もiMacもUPSに参加させましょう。うーん、フィリップス君50W食ってるように見えます。

開発:バックライトが蛍光灯だったりして。

基盤:次にiMac。おお、起動時に100W以上食いますね。Parallelsで2つのVMを起動。おおーっと、過去最高の248Wを記録しました。

開発:それでも6分は持つと。

基盤:でも安静時には50W。でこれが、全体の安静状態です。

基盤:ついでに扇風機も参加させましょう。

開発:電源パックアップ付きの扇風機w

社長:ある意味、生命線ですから。

基盤:扇風機は全力回転で7Wくらいですね。

社長:我社の全インフラ・ライフラインがこの1万円のUPSにつながっていると思うと、感慨深いですね。

基盤:全パソコンが同時に全力運転した時に、このUPSのキャパの300Wギリというところですね。

基盤:あれ?Power Panelの反応がなくなりました… このソフト、ホストの起動時にはまず安定して立ち上がるんですが…

開発:USBの接続がうまくいかなくなるんですかね。

基盤:Thunderbold口に移してみますが…だめですね。No device connected。ちょっとリブートします。

基盤:何回かQuitを起動をやってみましたが、どうもThunderbolt口なら10秒くらいで確実に接続するみたいですね。macOS的には認識してないようではありますが。

基盤:で、バックライトの消費電力ですが、これがRetinaの一番暗いモード。

基盤:一方、一番明るいモード。

開発:40W近い違いですね。バックライトってそんなに食うのか。

基盤:私が普通に使いたい明るさでは15Wくらいのようです。

社長:スマホでは時間が立つと自動的にバックライトを暗くするとかありますが、デスクトップでもあるんですかね。

基盤:うーん。… 省エネルギーにもスクリーンセーバにもディスプレイにも設定が見当たらないですね。

開発:凝ったスクリーンセーバとかって、逆にすごく電力食ってそうですしねw

社長:それでは仕上げに、UPSのテストをしましょう。電源を抜いて下さい。

基盤:では。ぶつっと。

UPS:ぴーっぴーっ。… … … …ぴーっぴーっ… … … …

社長:でも全て問題なく使えています。

UPS:ぴーっぴーっぴーっぴーっぴーっぴーっぴーっ

基盤:残り5分くらいで連続警告になるみたいですね。

基盤:では全電源電源回復。

開発:モニターをバックアップ系からはずせば、10分くらいってとこですかね。

開発:瞬電対策としてはもともと問題ないですが。サージ対策もありますし。

社長:全モニターが消えても困るから、自動的に暗くなってくれると良いですね。UPSとの設定でそういうことができるのかな。

開発:脳がないフィリップス君がそれをできますかね。USBなりEtherでコマンドを送れるくらいなら、設定に苦労もしてないんですけど。

社長:実はVNCクライアントかXサーバ機能があったとか。

基盤:あれ?裏をみたらフィリップスくんにはUSB-Cが1口、USB3が2口、あとEtherの口がありますよ?まあただのハブかもですが。

開発:ええー。こいつ、いやこの方はそういう高貴な生まれだったのですか。

基盤:ところで只今の室温、31.5度です。

社長:ああそういえば昨夜帰った時に、郵便受けにiMacのメモリとラズパイ3がはいってました。あと電子工作キットw

基板:まずはメモリを増設しましょう。仮想マシンのメモリが厳しいんで。

* * *

経理:でんこ家計簿、昨日の分が見れるようになりました。

開発:きのうも200Wベタですね。

社長:ソフト開発って電気食わない稼業ですねw

基板:フィリップス君のバックライトを暗くしたら安静時の総計140Wを切りました。

経理:ということは、2時間ごとに200Wと100Wをぴこぴこするグラフが見られるということですね。

社長:ああやっぱり、輝度をコンピュータからコマンドで制御したいですねぇ… メシ行ってきます。

基板:しかし、クラウドの仮想マシンて電気代のことを考えると、お得感が増しますね。

* * *

社長:かき氷を買ってまいりました。

基板:シャビイ?shabby?しょぼい?

開発:名前のわりには100円もするんですね。

社長:冷蔵・冷凍庫を失った当社としてのせめてもの暑さ対策です。体内から冷やしましょう。

経理:いえ、べつに電源を入れれば良いと思いますが。

基板:うん、これはなかなか、大人のかき氷ですね。シャグ。

開発:変な名前だと思ったらこれ、シャーベットの意味ですかね。なかなか。

経理:上にのってるレモンスライスがちょっと…

社長:冷凍みかんのようです。子供の頃は恐怖の対象でした。なるほどこれはシャーベットなわけですね。違いのわからない私。

基板:液状化し切る前に完食いたしましたw

* * *

scpを驚速化するソフトの開発に成功

開発:なんか変な時間から始業になりました。

社長:涼しい夜に仕事をするというのは合理的かと思います。

経理:そういえばでんこちゃんの家計簿が見れるようになりました。

基盤:この赤い線、世間一般世帯の平均ということだと思いますが、それにとても近いのが驚きですね。

社長:うちと違って一般家庭では夏場は冷房を入れると思うんですが、大したピークにも見えないのが不思議です。

* * *

開発:さて、問題のscpのアップロードですが、scp.c の中の source という関数の中のループで実行されています。ですが、そのあたりは 7.7と7.8で違わない。そこから呼ばれて実際に送信を行っているatomicio6という関数もです。

開発:で、scpがどこに出力をしているかなのですが、サーバへのコネクションを張ったsshに違いないと思うわけです。実際、転送中のプロセスはこんな形になっています。7.7と7.8で違わない。

開発:それでは、ssh は何をしているかというと、ssh.c の ssh_session2 から clientloop.c:client_loopを呼んでいて、client_loopではselectで待っている。何を待っているかと言えば、やはりサーバへの送信が可能になっているのを待っているのかなと思うわけです。

社長:pollじゃなくてselectなのがBSD的なんでしょうかね。私も昔はselectでしたが。pollのほうが使いやすかったので、すっかりpollになりました。

開発:しかし人の書いたプログラムの動作を追うには、ブレークポイント機能のあるIDEがないと手間ががかかるというのをつくづく感じますね。まあマルチプロセスだとちょっと厄介ですが、scp | ssh のこれとか、別にスレッドで良いと思うんですが。そのほうが性能も多少良いかも知れないし。

開発:で、output のselectの対象になってるサーバ向けのソケットのバッファサイズは87KBあるので、問題ないと思われます。そもそも 7.7 と同等でしょうし。実際これを512KBとかにしてみても、変化はありません。

社長:なるほど。となると、どこかでしょうもない遅延が入ってるんでしょうね。わくわく。

* * *

社長:ところで Vivaldi をメインブラウザにしてから2ヶ月になります。操作感的な面白さはやや飽きたというか、良し悪しな面もあるように思うようになりました。基本機能的なところで完成度が今ひとつに感じるところもあります。ですが、やはりVivaldiがいいなと思う点は、複数の別個のユーザとしてプロファイルを定義できて、使い分けられる所かなと思います。そしてセッションの保存と回復。現在開いているウィンドウ・タブのセットを名前付きで保存して、回復できる。これはまさに、昔からずっと欲しかった機能なわけです。

社長:ちょっと残念なのは、複数のセッションを並列で持てないように見える点。あと、セッションをまるごと削除できないようにみえる点です。あるいは、各セッションに含まれるウィンドウとタブを一覧表示する機能が無いように見えること。タスクウィンドウみたいので良いと思うのですが。

社長:Vivaldiには、ブラウザを使うにあたって、あるユーザとして、あるセッションの中で、あるウィンドウを開いているのだ、あるいは開くのだという使い方を、もっと明確に押し出してい欲しいと思いますね。だから、使い始める時に「デフォルトのユーザ」として「デフォルトのセッション」の中に居るのだということをわかりやすくしてほしい。あるいは「保存されたセッション」に「デフォルトのセッション」が無いのも片手落ちと思います。これはもやもやっとしているし、勝手に回復することになっているのが良いとも限りません。

基盤:Person1とか英語としてもイマイチですが、日本語版でもなにか工夫して欲しいものです。

開発:日本語のソフトだと「既定ユーザ」とかが好まれそうなw

社長:あとは複数のユーザ(プロファイル)の間でセッションというかウィンドウやブックマークを共有出来ないのも困ることがあります。たとえばこのセッションやブックマークはどのユーザと共有する、という設定ができると良いと思います。そしていずれかはそれらを、別種のブラウザとの間でも共有できると良いのですが。

開発:まあ抱き合せ機能で囲い込み合戦中でしょうからね。そういう共有のための標準化がされてしまった後に、Vivaldi独自の強みというのを維持し続けられるかも問題かなと思います。

社長:個別には実現技術的に難しい話ではないでしょうしね。

基盤:カスタマイズ能力を標榜するなら、カスタマイズを支援するウィザード的なものも充実してほしいですよね。沢山の設定項目の中でどれが自分の興味のあるものかとか。あるいは、プレカスタマイズされたテンプレート的なものを提供するとか。カスタマイズ情報のエクスポートとインポートって出来るんですかね?

社長:だれそれ監修の設定セットとかテーマとか、設定に名前を付けられるようになると良いですね。

* * *

開発:さてそれで、selectにラッパーをかけて、動作を観察しました。selectに 10ms以上かかった場合だけ出力しています。まず 低速な7.8の場合。

開発:[3]というのは、サーバと接続しているソケットのファイルディスクリプタです。一方、高速な7.7の場合。

開発:7.8では10msを大きく超えることが無く、また入出力が同時にreadyになることが多い。一方7.7では待ちが50ms程度かかることが多く、しかも送受信一方ずつしかreadyにならない。これが10倍の性能差の原因かと思われます。

社長:監視しているファイルディスクリプタの数の 8 と 7 の違いは何でしょう?

開発:selectの第一引数の仕様はなんだか混乱していて、あまり真剣に設定したことが無いですね。実際このケースでは、待っているのは [3] だけなんです。

開発:えーと。ここは単にサーバと通信を双方向中継してるだけだと思うんですが、なんでこんな複雑そうに見えるかと言うと、sshはスレッドを使ってないんですね。PAMスレッドでしか使ってない。それで、I/Oをnonblockingにして、自力で双方向の中継を実装している。こういう実装法だと、上り下り両方がreadyの場合にも、片方ずつしか中継できないんで、nonblockingとは言え、並列性が活かしきれない気がします。特にマルチコアでは。

社長:なぜにそのような実装になっているんでしょうね?

開発:sshは1995年以前に作られたもののようです。当時は標準のスレッド技術が無かったと思います。それに、スレッドだとメモリを余計に食うというのはありますよね。あとは、やりたい場合にはですが、上り下りの間の同期を制御しやすいとか。

社長:確かに… DeleGateでも色々なスレッドとお付き合いしました。

開発:えーと。もっと恐ろしいことがわかりました。scp から ssh にデータを送っているわけですが、これは pipe でできていました。

社長:pipe ってバッファサイズが 4KBとか…

開発:最近では64KBのようですが。でも、ファイルを読んでただ送っているだけなわけです。なら、SSHにファイルディスクリプタを継承すれば良いのにと思うのですが。まあ、パイプ経由でコマンドも送るんでしょうけど。

社長:Windowsではソケットのハンドルはファイルディスリプタ的に継承されないですしね。

* * *

開発:ふぁあぁあ… よく寝ました。

社長:それでどうなりました?

開発:sshのコードを3時間ばかり格闘したのですが、どうもその、サーバとの通信状況でパケットの送受信の戦略が変わるようでもあり、あるいはその先のTCPの転送経路が何か学習するのか、振る舞いがつかめませんでした。とにかく、送受信のバッファを大きくすれば良いというようなシンプルな話では内容です。

開発:ただ、動作原理はわからないですが、途中にアプリケーション層でのTCP中継器を挟めば問題が回避できることは確かです。

開発:そんなわけで、sshがサーバにコネクトした後に、そのソケットに一段フィルター的に中継プロセスをかませることにしました。

開発:特長は、select もスレッドも使ってないところです(笑)

開発:でもってこれを、sshconnect.c に挿し込みます。

開発:そして、環境変数 _ISFENV を定義して ssh や scp をやると、このフィルタが挿入されるという仕掛けです。やってみます。

基盤:おお、10倍速達成!

開発:socketpairにAF_UNIXを使っていると、macOSではNODELAYが出来ないと文句を言って来ますすが、まあそもそものTCP立ち上がりの問題なので、実害はありません。

開発:この対策は、レイテンシがめっちゃ長い外部サーバにはそれほど効きません。USサイトとはRTTが130ms程度ですが、まあ2倍速くらいかなという感じです。

開発:最果ての地、フランクフルトではこんな感じ。

社長:まあでも、2倍高速化すれば十分じゃないですか。

基盤:遠隔でも、ライトセール間なら5MB/sくらい出ますので、一旦ライトセール東京に持っていって、そこからさらに先に配るのが良さそうですね。

開発:そういえば現在、xsoへのアップロードは30MB/sくらい出ます。ところが、macOSでやってみたら、3MB/sくらいしか出ないんです。

開発:ところは腹いせにでっかいファイルを送ってやったら、ジョジョに加速して、34MB/s に到達したりするんです。

基盤:不思議過ぎる… 何がどうこでどう調整されているのやら。

社長:相手によってヒューリスティックに戦略を変える必要があるのかも知れないですね。

開発:奥が深そうです。

社長:それはそうと、せっかく作った isfilter プログラム、なんかの形で公開しましょう。

基盤:このブログじゃだめなんですか?w

— 2020-0805 SatoxITS

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

はじめての自作NFSサーバ

社長:「はじめての自作◎◎」って悪くないタイトルですよね。

開発:まあ、一般にあまり自作する事のないものだと違和感はあります。

経理:ベストセラーにはなりにくそうですね。

基盤:はじめての自作宇宙船とか。スペースXって結局、国鉄の民営化みたいのとは違うんですかね?

* * *

開発:ああそれで、NFSサーバが固まっちゃう問題は再現しました。

社長:なるほど、自分自身につなごうとしてタイムアウトを繰り返していると。

開発:unfsdを単一プロセスにしていたのでわかりやすかったです。要は、自身がマウントしているディレクトリの下に、自身のマウントポイントが見えているので、再帰しちゃってるんですね。

社長:多段のループだと検出は難しいですが、自分自身なら検出しても良いのにね。

開発:それはそうと、こうなった場合のmountテーブルのクリア方法がわかりません。umount は効かない。diskutil umount force も効かない。

社長:ひょっとして、unfsdを殺しちゃってるからじゃないですか?誰も応答しないから、後片付けができないとか。

開発:あ… そうかもです。unfsd を起動して、umount … ああ、昨日見たこれがぽっと出ました。

開発:でもって Disconnect All。おー、mountがクリアされました。

社長:メデタシ。

開発:「昨日見たFUSEみたいの」なんて、失礼な事を書いちゃいました。とんだ濡れ衣でしたね。

社長:要は、私は eject しちゃいましたもうここにはいません、みたいなメッセージをクライアントに返してから死ねばよいのでしょうかね。

開発:まあ、原因もわかりましたし、方向性は見えましたのでおいおい。

開発:それで、ファイルをクリックで開く時に、それをどう扱うかは結局、拡張子で判断するのが趨勢なわけです。まあ、可変長文字列なのでまさに拡張性もありますしね。なので、

社長:ちょっと待った。ボウリングの試合に行ってきます。

* * *

社長:ただいま。

基盤:どうでした?

社長:130台で始まり、徐々に修正して、200台で終わりました。最初はフォームもタイミングも変でわけがわからなかったんですが、リリース時に右肩が突っ込んだりぶれてた事に気づいたんです。回転軸がぶれては、全てが台無しです。

社長:ああそれで、機能を持つファイルの名前ですが、最後は拡張子で終わる。ファイル名の先頭は本来の名前であるべき。だとすると、name++function.ext といった形になるのかなと思いました。

開発:「++function」の記法は悩ましいですね。?function でも良さそうには思いますが。

社長:「?」は伝統的にshellでファイル名の一文字マッチングに解釈されちゃうのが嫌なんですよね。まあ、おいおい考えましょう。

開発:ではとりあえず「++」がファイル名に入ってたら実行することにしてみます。

開発:またループすると嫌なので、$HOME/unifsv を $HOME/unifcl にマウントすることにします。まずこういうふうにexportsして、unfsdを起動。

開発:でこれをマウントする。

開発:ここにある4つのファイルは全部同じファイルです。ハードリンクしたものです。で、中身を読み出すと、NFSのクライアント側から見た ++ 付きのファイルだけが、実行された結果として見える。

開発:でこれをFinderで開いたりブラウザで開くとこうなります。

社長:ふーむ。機能的には出来てます。Finderやエクスプローラにファイルの名前以外でデータ型を、MIME Content-Type で伝えられると良いのですけどね。

開発:うーん。少なくとも最初のNFSが出来た時にはまだ MIME も無かったですしねw。

基盤:その後のNFSではどうなんでしょうね。

開発:grep -i mime *.h .c … unfs3には無いみたいですね。NFSv4にはあるんですかね… あった。

開発:まあ、これをNFSクライアントが、つまりファインダーやエクスプローラが見てくれるかどうかですが…

社長:見てくれるなら、CGI使ってヘッダにContent-Typeを返す必要なくなりますね。

開発:ものによっては、HTTPサーバである必要もなくなりますね。単にNFSマウントしてfile URLで開けば良い。

開発:ですが、せっかくHTTPでURLにいろんな機能をもたせて普及したわけですから、それをそのままファイル名にも使いたいのも確かです。

社長:HTTP的に考えれば、クライアント側に見えない隠しファイル的に、いろんな属性を付加できればいいんじゃ無いかととは思います。

開発:そうですが… クライアント側から一律な変換機能を叩けるところが、NFSでやる面白さなんじゃないかとも思うわけです。

開発:どうもその、一度ディレクトリをキャッシュしてしまうと、その中に無いパスを追ってくれない的なクライアントの作りになっているように思われるんです。そうなると、無限の組み合わせのある隠し機能というかパラメータを指定することが出来ない。

社長:でも、巨大なディレクトリの中の一つのファイルを開くこともあるわけで。クライアントとしてそういう理不尽な実装をしますかね?

開発:ああでも、これも、ディレクトリの最終変更日付を変える手でしのげますかね。あるいは、このディレクトリ、このファイルはキャッシュするなという指示がNFS的にできるのかもです。明日また確認します。

— 2020-0803 SatoxITS