💡

FireDBG: Rust ではじめるタイムトラベルデバッグ

2023/12/26に公開

はじめに

Rust のデバッグ辛すぎという話は Rustrician にはよく聞く話で、 Rustプログラムのデバッグ辛すぎ問題 という記事もあるくらいです。
FireDBG という新しいデバッガーが SeaQL [1] からリリースされました。
リリースは 2023/12/11 で、直後の週末に使ってみた感想を投稿する予定だったのですが、コロナに感染し身も心も記事も寝ていたので、クリスマス明けに投稿に至りました。

Rust におけるデバッグの現状

現在、LLDB と GDB というデバッガーが有力で、Rust を使う人たちはそれらを駆使してデバッグを行っている、、、と思いきや、私の周りでは println! でログに出力してデバッグしている人が多いです。
私の開発環境は Apple Silicon Mac なので、デバッガーは LLDB しか使えないのですが、上手く使いこなすことができず、 println!dbg! でログに出力して挙動を観察しています。
Rust は開発体験をサポートする機能が充実していると言われることも多いですが、デバッグに関してはブルーオーシャンといっても良いくらいです。

FireDBG とは

FireDBG は SeaQL が開発した Rust のデバッガーです。
従来のデバッガーはブレイクポイントで止めて、状態を確認したり、ステップ実行することができますが、FireDBG にはその機能は現在はないようです。

FireDBG はタイムトラベルデバッグ [2] という機能を持っています。
FireDBG によってデバッグを行うと、メソッド呼び出しの Call tree を作り、各 method call ごとに引数の値や戻り値を確認することができます。
従来のデバッグが前進しかないのと比較すると、タイムトラベルデバッグは前進と後退ができるので、デバッグの効率が上がります。

一方、その時の状態をアドホックに確認することはできないので、代わりに確認したい変数を FireDBG に収集させる機能も用意されています。
また VSCode の extension を使うことで、視覚的に Call tree、引数、戻り値を確認できます。

ブレイクポイント型とタイムトラベル型のどちらを使いたいかはケースバーケースですが、現在の Rust のデバッガーの状況を考えると FireDBG は女神と行っても差し支えないくらいの存在です。

FireDBG を使ってみる

公式の Getting Started を見て実行するのが一番ですが、ここではかいつまんで紹介します。

インストール

詳細は公式の Getting started を読んでください。
以下は 2023-12-17 時点の情報です。
動かない場合、公式の情報を確認してください。

FireDBG を動かすには以下の Rust と VSCode が必要です。

  • Rust v1.74.0 以上
  • VSCode v1.80.0 以上

概ね、VSCode の FireDBG for Rust extension と FireDBG のバイナリーをインストールすれば終わりです。
バイナリーは extension インストール後に VSCode からもインストールできますし、以下のコマンドでもインストールできます。

curl https://raw.githubusercontent.com/SeaQL/FireDBG.for.Rust/main/install.sh -sSf | sh

実行方法

試しに FireDBG の Getting started を読みながら examples を実行してみれば使い方は簡単に分かります。

git clone git@github.com:SeaQL/FireDBG.Rust.Testbench.git
cd FireDBG.Rust.Testbench/getting-started
vscode . &

VSCode を使ったデバッグの方法がいまいち分からず、現在は terminal から以下の手順で実行しています。

# 1. FireDBG の対象となる Binary target のリスト
firedbg list-target

Available binaries are:
	quicksort
...

# 2. {binary} を解析
firedbg run {binary}

# 3. 解析済みリストの表示
firedbg list-run
Available `firedbg` runs are:
    1) quicksort-1703520428117.firedbg.ss
...

# 4. 解析結果を VSCode で確認
firedbg open 1

解析結果の確認

クイックソートの解析結果は以下のように表示されます。

① Call Tree の領域では、 quick_sort が呼び出された後、quick_sortpartition が再帰的に呼び出されているのが可視化されています。
② Variables の領域ではメソッドの引数、戻り値に加え、手動で fire::dbg! した結果を表示させることができます。 図では初回の quick_sort を選択しています。Call Tree でメソッドを行ったりきたりしながら、値の推移を観察することで、ブレイクポイントを置いたデバッグより効率よくデバッグができると思います。

FireDBG は Web アプリケーションをデバッグできるのか

公式ドキュメントでは主にユニットテストレベルの複雑さのコードを対象にしていました。
では、Web アプリケーションをデバッグできるのか試してみます。

今回は個人で開発している Web アプリケーションで試してみました。

cd server
firedbg run server
...
warning: server was compiled with optimization - stepping may behave oddly; variables may not be available.
[2023-12-15T15:11:08Z INFO  firedbg_rust_debugger::debugger] Finished.    target: 16.822798083s    total: 20.087954708s

サーバーが立ち上げたらリクエストを送ってみます。

grpcurl -plaintext -H 'authorization: Bearer XXX' '[::]:50051' cleanArchitectureWithRust.user.UserService/ListUsers

結果がこれです。

サーバーの立ち上げまでの Call tree がでていますが、リクエストを処理した時の Call tree はでてきませんね。残念です。

main thread しか解析できないわけではなく、別スレッドで動いている health check はちゃんと解析できています。

health check は起動後、loop して DB に ping しつづけるだけなので、Call Tree には1つのメソッドしか表示されていません。

検証した Web アプリケーションは Clean Architecture の構成を取っており、レイヤーごとに crate を分離しています。
状況から判断するに、FireDBG は実行した crate 内部の Call Tree だけを解析対象としているようです。
今後、他の crate の中まで解析する方法が提供されれば、Web アプリケーションのデバッグはとても捗ると思います。
FireDBG は公開されてまだ一ヶ月経っていないライブラリーなので、今後のアップデートに期待です!

おわりに

FireDBG は導入がとても簡単です。
既存のデバッガーより遥かに効率よく内部状態を観察できます。
ユニットテストのデバッグにはとても頼りになるはずです。

その他

「FireDBG は Rust の闇を照らす花火となるか」というタイトルも考えたのですが、滑るのが怖かったのでやめました。
とはいえ、FireDBG は Rust のデバッグの闇を照らす花火となる可能性を秘めています。
SeaORM が継続的にサポートしてくれることを前提に考えると、Rust におけるデファクトスタンダードのデバッガーなっていくと信じています。

参照

脚注
  1. SeaQL は SeaORM を作っている団体 ↩︎

  2. Microsoft の Time Travel Debugging - 概要 を読むと詳しく理解できる ↩︎

Discussion