2 ポイント 投稿者 GN⁺ 2023-11-27 | 1件のコメント | WhatsAppで共有
  • fish-shellのRustポートは「大部分」が完了した状態で、計算方法によって C++ SLOC削減基準で60% から Rust SLOC対C++ SLOC基準で74% まで進んだと集計されている
  • 残る最大の作業は readerと入力システム の移植で、reader 3.5k行、screen handling 1.3k行、input 1k行、pager 700行が互いに強く結合している
  • すべてのC++コードは削除される予定で、途中で 部分的なRustリリース は出さず、fish 4.0のようなリリースはRustのみを含みC++は0の形を目標としている
  • Windowsポートは計画されたことがなく、Rustへの移行はWindows対応問題の解決策ではなく、MSYS2/cygwin環境の利用者はRustにそのターゲットがないため更新が止まる可能性を懸念している
  • 完成したポートの性能はまだ確定しておらず、初期結果は有望だが一部のケースでは 約20%遅くなる可能性 もあり、最初のRustリリースにはベータ版が必要だと判断している

Rustポートの進捗状況

  • fish-shellのRustへの書き直しは「大部分」が完了した状態
  • 進捗率はどの基準で数えるかによって変わる
    • C++ SLOC削減基準では60%
    • Rust SLOC対C++ SLOC基準では74%
  • 一部のコードは最後の呼び出し元がなくなれば削除できる重複した足場コードである
    • 例として wgetopt はすでにRustへ翻訳されているが、最後のC++呼び出し元が移植されるまでC++版を残している
    • すべてのC++呼び出し元に変換用コードを付けるより、この方式のほうが単純である
  • 最後の呼び出し元がなくなったあとに重複コードが削除されると、ドミノのように整理される部分がある

まだ残っている大きな作業

  • 最大の残存コンポーネントは readerと入力システム
  • 関連コードは互いに強く結合している
    • reader: 3.5k行
    • screen handling: 1.3k行
    • input: 1k行
    • pager: 700行
  • その後には一部の残存コードとビルドシステムの 脱C++化 が残っている
    • cmake の削除
    • cargo が必要な作業をすべて処理するように移行
    • ドキュメントやcompletionファイルのビルド・インストールまで cargo が担当する必要がある
  • fishのビルドはRustコードのコンパイルだけでなく、複数の補助生成物を含むため単純な移行ではない
  • この作業は「drive-by contribution」に向いた種類の作業ではない

リリース計画とバージョンの流れ

  • fish-shellは 部分的なRustリリース を出す計画はない
  • たとえばfish 4.0は完全にRustだけで構成され、C++は0の形になる
  • 通常はベータ版とリリース候補版をやめているが、今回の移行はベータ版を出すに値する変更だと判断している
    • これまではベータ版とリリース候補版が十分なテストを受けられなかったため中止していた
  • Rust版へ移行する前に、C++ベースの 3.7.0中間リリース も望んでいる
    • Rust版を扱えないプラットフォーム向けの、よりよい出発点にするため
    • 3.7.0は3.6.1に一部変更をバックポートした形である
  • 3.7.0作業は Integration_3.7.0 branch で進められている
    • 予備の CHANGELOG もある
    • 主な変更にはキー組み合わせタイムアウト、history-pager改善、レンダリング不具合の修正、より高速なglobが含まれる

残っているファイルと具体的な範囲

  • 2023年12月1日時点で残っているファイル一覧は次のとおり
src/fish_indent_common.cpp
src/fish_indent.cpp
src/fish_key_reader.cpp
src/builtins/bind.cpp
src/builtins/commandline.cpp
src/fish_tests.cpp
src/pager.cpp
src/reader.cpp
  • この一覧は残っているC++移植範囲をファイル単位で示している

誤解の訂正と制約

  • すべての C++コード は削除される予定
  • Windowsポートは計画されておらず、過去にも計画されたことはない
    • C++もWindowsで十分サポートされるため、Rust自体がWindowsポート問題を解決するわけではない
    • Windowsポートの問題は言語ではなく、WindowsがUnixではない点にある
  • 名前とマスコットは変えない
  • タグラインに「written in Rust」を追加しない可能性が高い
    • fishshell.comではRustで書かれている点に言及する可能性はある
    • 2024年9月の追加議論でも、タグラインに「written in rust」を入れないという立場が再確認された
  • 完成したポートの性能はまだ不明
    • 初期結果は有望
    • 一部のケースでは 約20%遅くなる可能性 もある
    • 初期ポートが終わってもプロジェクトが終わるわけではなく、やるべきことは多く残っている

WindowsとMSYS2/cygwin利用者の懸念

  • ある利用者はMSYS2環境でfishを使っており、MSYS2がPOSIXユーティリティを提供するためfishがうまく動作すると説明している
  • RustはcygwinまたはMSYS2ターゲットを提供していないため、Rustへの書き直し後はfishをcygwinまたはMSYS2ターゲット向けにコンパイルできなくなると懸念している
  • この利用者はRust移行によって一部のWindows版fish利用者の更新が止まる可能性があると見ている
  • この懸念は作業や言語を非難するものではなく、WindowsがUnixではないという制約をあらためて示す内容として提示されている

1件のコメント

 
GN⁺ 2023-11-27
Hacker Newsのコメント
  • 正しく理解しているなら、C++からRustへの段階的な書き換えを進めつつ、最後まで動作する状態を保つというのは驚き
    進行速度も非常に速いし、まだfishを使ったことがないならぜひ使ってみてほしい。デフォルト設定が良くて、カスタマイズしなくても使いやすいシェルで、数年前にbashから移行して以来、戻ろうとは思っていない
    おまけに、めったに使わないうえ直感的でもないbashのforループ構文を毎回ググらなくて済む

    • 段階的に進めるわけではないようだ
      「Rustが一部だけ混ざったリリースはしない予定」で、たとえばfish 4.0は 完全にRust、C++ 0% で出すつもりらしい。その前にC++だけの3.7.0も出して、Rust版に対応できないプラットフォーム向けのより良い出発点にするつもりのようだ
      https://github.com/fish-shell/fish-shell/discussions/10123#d...
    • スクリプトは今でもBashで書くか、単にPython/Perlを使うことが多いが、ターミナル利用に関しては間違いなくFishのほうが良い
    • 覚えやすいBashループの例として、インクリメントするインデックスは for ((i = 0; i < 10; i++)); do echo $i; done のように書ける
      配列の走査は foo[0]=a, foo[1]=b を用意してから for i in ${foo[@]}; do echo $i; done という形でできる
  • 書き換えの動機はもっと詳しく説明されている
    https://github.com/fish-shell/fish-shell/pull/9512#issuecomm...

    • メンテナーの文章が成熟していて論理的で、適度にユーモアもありつつ断固としていて、これまでFishを試そうかと思うだけだった気持ちが、素晴らしいプロジェクトを見逃していたのかもしれないという方向に変わった
    • C++17への移植は「面倒すぎる」と見なしつつ、新しい言語で全部書き直すのは構わないと考えるのは、いろいろなことを物語っている
      結局のところ、開発世界全体の新しくてキラキラしたもの追いという話にはなかなか勝てないと思う。それでもFishは使わないが、うまくいってほしい
  • Fishを約4つのOSで毎日使っていて気に入っている立場からすると、この書き換えは本当に楽しみで、コードベースの規模と複雑さを考えると進行速度は驚異的
    自分を含め、多くの人が貢献しやすくなる効果もありそうだ。あまり注目されていないが、さらに期待しているのは、今後fishが wchar_t の代わりに UTF-8 を使うようになる計画だ。UCS2とUTF-16はソフトウェアにとって厄介者で、RustはUTF-8の扱いがずっと楽だ

    • 複数のコンパイラを1つのコードベースでサポートしようとすると、さらに複雑になる
      sizeof(wchar_t) はMSVCでは2バイトなのでUTF-16、gccでは4バイトなのでUTF-32になる
  • Fishは過小評価されているシェルだ
    POSIX互換性を捨てるといった強い選択をしているが、その結果として非常に良いシェルになっている。10年以上使っているが、今でも気に入っている
    Fishのシェルスクリプトも非常に書きやすく、人間工学的なbashのような感じだ。どんなプロジェクトにも欠点はあるが、自分がやろうとしていたことを実際に妨げられたことはない

  • zsh + spaceship を使っている立場として、Fishをメインシェルに移すとどんな利点があるのか気になる
    bashスクリプトはあまり使わないので、スクリプト面はそれほど重要ではない

    • すでにzshを望みどおりに設定してあるなら、大きな利点はあまりないだろう
      Fishの大きな強みは、設定なしですぐ理想的なシェルに近いことだ。補完は最初から動くし、履歴の検索も簡単で、履歴ベースのコマンド補完もできるし、プロンプトの選択もブラウザを開く程度に簡単だ。zshのように深くカスタマイズもできるが、デフォルトのままでもかなり良いシェルになる
    • 2017年にzshではなくFishを選んだ理由は、欲しい機能が標準で入っていて、体感ではるかに速かったからだ
      その後は シェル設定のメンテナンスにほとんど時間を使わなくなって、それが良かった
    • 速度のためだ
      Fishはzshでプラグインが必要だった多くのことを標準でやってくれる。zshのプラグインは遅くてシェルの起動に3秒以上かかっていたが、Fishはプラグインを入れてもずっと速く起動する
    • 初めて正しいディレクトリに fish_prompt.fish ファイルを作り、その中に fish_prompt 関数を書いて文字列を標準出力に出し、自分でシェルプロンプトを作ったとき、zshを消しかけた
      $PS1 にあれこれ押し込んでうまくいくことを祈る方式には戻りにくくなる。数日だけでも使ってみることを勧める。当然だと思っていたものの何がシェル固有の機能なのか見えてくるからだ。最悪でも「自分の好みではないな」と言って、bashやzshなど好きなシェルに戻ればいい
    • 数年前にzshからFishへ移行したが、機能はほぼ同じなのに、Fishの設定ファイルはzsh設定の10%くらいの大きさだ
      欲しいものの大半が標準で提供されていて、今は fzf.fish プラグイン1つだけを使っている
  • もともと最速クラスのシェルの1つが、さらに速くなる可能性が高い
    zshからFishに移ってから ターミナルでの生産性がかなり上がった

    • そこには賭けない
      リンク先によれば、完成した移植版の性能がどうなるかは実際にはまだ分からないという。初期結果は有望だが、場合によっては 約20%遅くなる 可能性も十分ある
    • C++とRustのあいだに、性能差がそこまで大きいとは思わない
      ほぼ互角で、明確な勝者はいない可能性が高い
    • どういう作業フローでシェル性能がボトルネックになるのか気になる
      普通は他の仕事を引き渡す 接着コード に近いものだと思っていた。パイプの効率の問題かもしれないし、bashで丸ごとプログラムを書く変わり者たちのせいかもしれないが、Fishには生活の質を上げる改善がたくさんあるのに、速度を中核的な利点として挙げるのは少し珍しく見える
    • C、C++、Rust、その他の言語の差が意味を持つほど速くタイピングしたり作業管理したりはしないはずなので、Fishがほかに何か提供しているのか気になる
  • Fish を1年使ってきた。
    gvmnvm のような一部のスクリプトが動かないように標準互換性を壊している点は気に入らないが、zsh で普通は自分で設定していた機能が一通り入っている。複数のマシンで zsh の設定を試しているうちに諦めて、全部デフォルトの Fish に切り替えた。
    すでによく動いているのに、Rust に移植して何が得られるのかは正直よく分からない。セキュリティのためだというなら、Fish を悪意をもっていじれる何かがすでにシステム上で動いているのではないかと思う

    • もともとの Rust 議論でも出ていたように、Rust に移す理由はいくつかある。
      主には コントリビューターの確保 と、メンテナーが安心して追加できる非同期/並列モードに近い。
      [1] https://github.com/fish-shell/fish-shell/pull/9512
  • Fish は良い。
    ZSH+Prezto から単に Fish だけを使う形に変えたが、不満はなく、ずっと速い。サーバーには全部 bash があり、bash スクリプトもまだ使っているが、日常的なターミナル作業 には Fish で十分だ

  • Fish には前から興味があったが、POSIX 非互換 なので敬遠していた。
    この点で困ったことや回避方法を共有してくれる人がいるとありがたい

    • Fish は bash/shell スクリプトの代替ではなく、対話型シェル として使うためのものなので、POSIX 準拠かどうかは実際には大きな問題ではない。
      欠点は少し文脈の切り替えが必要なこと。特にずっと bash/zsh を使ってきたならなおさらだ。シェルをユーザーインターフェースとして使う場面と、bash/sh をインタプリタとして使う場面を区別するのは個人的には簡単だが、誰にとっても直感的とは限らない。
      また、POSIX 互換シェルを普段使いのシェルとして使わなくなってからは、以前なら bash で済ませていたスクリプトを、より早い段階で汎用言語に格上げするようになった
    • Bash/zsh スクリプトはそのまま Bash/zsh で実行すればいい: bash script.sh
      Fish を使い始めた当初は POSIX 非互換が気になっていたが、別の文法を少し学んで慣れてしまえば、Fish のより sane な文法はその手間に見合う価値があると思う。今ではターミナルをずっと楽しく使えている。
      しかも 90% の時間は POSIX 互換を守る必要がなく、最近は多くのスクリプトや拡張も Fish をサポートしている。企業環境では標準である Bash/zsh を引き続き使っている
  • なぜ Rust に置き換えるのか気になる。
    C++ コードベース が手に負えないほど大きくなっていたのだろうか?