GShell 0.1.0 − Go1.15と内蔵find

基盤:8月11日にGo 1.15 がリリースされてたので更新しました。

基盤:以下がハイライト。

開発:リンカーが高速化って動的リンカーのことですかね。まずはビルド。これまでの1.14.3では…

開発:新作1.5では…

社長:コードが1MBくらい小さくなりましたね。

開発:この1.14.3はMacMini 3.6GHz i3x4で、1.15はiMac 3.7GHz i5x6で動かしているという違いがあります。gshのnopコマンドで比較すると、それなりの違いは見られます。

基盤:最速で比べると 26.8us : 23.9us だから、10%程度iMacのほうが速いですね。

開発:まだiMacは暇人ですしね。そのわりには値がぶれますが… まあ1コアだけ使う分にはほぼ同等と考えて良いようです。で、hello.goはというと。

開発:go run は239msが194msに19%高速化します。この理由はホストの10%の性能差には収まらないような。比較のためにCのバイナリは2.6msから2.1msへ。あーこれは20%ですね。CPU以外の足回りも含めると、 MacMini より 20%くらいiMac27のほうが速いみたいな。

基盤:大金をはたいた甲斐があったようですね。

開発:ところが、ビルドされたバイナリの起動は3ms台から6ms台に、2倍くらい遅くなります。なんなんでしょう?プラグインの動的リンクは速くなったように見えますが、これは再現性が無い。

社長:なんにしても、GShellにとってはSubstantial というような改善には見えないですね… まあ、利用法によるんでしょうけど。

開発:かといって特に新たな問題もないようですから、これからは Goは1.15で行こうと思います。

* * *

開発:さて、当面取り組みたいのは2つ、ひとつは内蔵find + 内蔵grep の検索結果で得たファイル名を vi などの外部コマンドに渡す機能。これはたとえば検索結果を環境変数に入れるとか、which や history の拡張のように!とかでファイルを呼び出せるようにする。

基盤:その機能はめっちゃ欲しいですね。

開発:もうひとつはfindの高速化。どうもGoのディレクトリスキャンはCで実現した場合より2倍遅いんです。これは os パッケージなりでディレクトリエントリを返す時に、エントリにあるファイルをGoが勝手に開いてソートして返しているせいではないかと昨日は格闘して疲れました。勝手に開くくせに、返してくるデータの中にはGoが stat システムコールで得ているはずのファイルのブロックサイズとかデバイス情報とかが含まれていないんです。これでは find の -ls とか du 互換の機能を作るのに使い物になりません。内蔵tarも作れません。で syscall パッケージでトライしたのですが、それでもまだダメっぽい。なので、これはこの際、ディレクトリのスキャンを並列化しようかと思います。

社長:ある意味面白い方向へ後押しされてますね。

開発:それにしても彼らがそういう「抽象化」とか「OS独立性」を実現したい気持ちはわかるのですが、ディレクトリのスキャンとかファイルの属性とかは、とうの昔にOSを超えて共通のものになっています。なのに今この時代にそういうところで引っかかってのってなんだろうって思うんです。

社長:10年前には片付いてた問題のように思いますけどね。そういうOSの太古の脳の部分にあれからまた新しい非互換性が生じたとは思えないんですが。

基盤:ひょっとしてAndroidに無いものは削りたいとか…

社長:Goでshellを書くとかシステム管理コマンドを作るとかは想定してないのかもですね。

社長:なんだかしらす丼が食べたくなったので食事に行ってきます。

* * *

社長:帰りました。そとは今日も夏でした。

社長:ところで私は、うちの玄関を出た時に見えるこの景色が結構好きです。

開発:電線の目障りがなければもっと良いのですが。

基盤:肉眼で感じる高さ感が消失しているのが面白いですね。

社長:それで、なんか夏らしさを写真に取ろうかと思ったのがこれ。

社長:アスファルトと夏草と短く暗い影。

基盤:残念ながらまったく伝わってこないですね。

社長:夏の撮影者。

基盤:これは少し感じるものがあります。

社長:電線と民家がなければなーと思いますね。

開発:北のベランダからポールを伸ばしてその先にカメラをつけるという計画です。

* * *

開発:さてさて、find 結果のファイルのリストを後続のコマンドで利用する機能にですが。

社長:できましたか。

開発:機能そのものはすぐに出来たのですが、ユーザにそれをどう引用してもらうかが問題でした。結果にユーザが名前を付けるのも良いのですが、ちょっとかったるい。で考えたのは、N番目のコマンドの実行の結果得られたファイルのリストを !Nf というふうに参照する、というものです。こんな感じです。

開発:行頭から -grep xxx で始まるのは、find . -exec grep xxx "{}" ";" の短縮形です。

社長:ファイルの名前による探索と中身による探索が一体化しているわけですね。

基盤:これは普通に便利。

社長:思うに従来のshellって、コマンドを起動するところまでは世話をするけど、コマンドの実行結果をどう他のコマンドに引き継ぐのかという所がほとんど無い用に思いますね。

開発:shellが直接関与している結果としてはコマンドの終了コードくらいですかね。あとは、コマンドの出力ストリームを他のコマンドにパイプで渡してやるくらいな。

社長:ファイルの中身の構造に関与しないところがUnix的な良さではあったと思うのですが、それがコマンドの実装に負担をかけていたことはあると思います。コマンドの実行の結果ファイルのリストが得られるなら、それを標準メタ情報出力的なファイルに出してもらって中継するとかが良いですかね。

開発:名前の付いたファイルの状態を保存する、ファイルの名前で他のコマンドにそれを伝える、というのは自然だとは思います。ただ、メタ情報については、名前と値の組とか、あるいはもっと構造的データ型式を定めてあげるのが良いかなとは思いますね。

基盤:今的にはJSONとかXMLでしょうか。

開発:それは嫌だなー… まあ環境変数的に、名前と値の組。値の内部構造としては… まあJSONでもいいのかな。

社長:上意下達が環境変数なので、下からの結果の戻しも環境変数と同じ構造になってれば良いですね。

開発:まあ、プロセス間でメモリマップしてやりとりすれば、ファイルであることを意識しなくても済みますしね。ファイルだと、第三者や時間を超えて情報を共有できるのが魅力です。

社長:Go言語間であれば、データのバイナリ表現であっても良いですよね。テキスト型式である必要は無い。

開発:いわゆる .conf tか .rc とかの初期設定ファイルにしても、そのための特殊な文法を導入する必要はなくて、Goで書いてコンパイルして動的リンクして組み込めば良いと思うんですよね。ユーザはGoだけ知ってればよいし、設定記述の構文的な間違いはコンパイラが見つけてくれるし、起動も速い。

社長:プラグインはGoの核心ですね。

開発:並列findの件は明日取り組みたいと思います。

-- 2020-0815 SatoxITS