最初の記事は何にしようかなーと思ってたんですけど、Twitter でたまたまいつか読もうと思っていた論文の解説を求めているツイート(これ と これ)を目にしたので論文紹介をしてみようと思います。
この論文は USENIX ATC (Annual Technical Conference) という OS の準トップ国際会議で 2017 年に発表されました。著者は主に Mozilla の方々です。論文は こちら、発表スライドは こちら にあるので興味のある方はご覧ください(アカデミアの方が作るスライドとはちょっと趣が違いますね)。ちなみに論文の extended version が arXiv にあります。
プログラム実行を記録して再生(record-and-replay)できるシステムがあると、例えば再現が難しいバグのデバッグなどの役に立つため嬉しいです(性能オーバーヘッドが小さいとなお良いです)。そういうシステムを実現する手法は色々と提案されているのですが、既存手法はデプロイが容易ではないという大きな問題があります。例えば仮想マシン上での記録(重たい)、カーネル/コンパイラや言語のランタイム/ハードウェアへの変更などが必要だったりします。そこで、デプロイが容易なユーザレベルの record-and-replay システムである
そもそもどういう情報を記録したら実行を「巻き戻して」再生できるのでしょうか?全ての事象を記録しようとすると(事象とは何か、またどうやって実現するか、はさておき)当然ながら容量も性能オーバーヘッドも大変なことになるでしょう。そのため一部の事象を記録して一部は再実行することで再生を実現するのが良さそうです。プログラム実行が全て deterministic(決定的。例えば加算命令は入力が同じなら出力は常に同じなので決定的です)であるならばそもそも難しいことはありません。ただ実際には nondeterministic(非決定的)な要素があるので(例えば
そこでプログラム実行を適当に区切っていき、区切りの中の全ての非決定的な事象と区切りへの入力を記録します。再生時には、これらの記録を再生した上で残りを再実行します。理屈の上ではこれで記録時と再生時の挙動が一致するはずです。
論文では以下のデザインについて述べられています。マルチスレッドプログラムにおけるデータ競合、システムコール、非同期イベント(コンテキストスイッチやシグナル)、共有メモリ、非決定的な命令(前述の
さて、上記の実装ではシステムコールによる変更の記録が大きな性能オーバーヘッドを引き起こします。記録対象のプログラムがシステムコールを呼ぶたびに 4 回もコンテキストスイッチが生じるためです(システムコール前と後に
普通に考えたら C のライブラリ関数をラップするライブラリを用意してプリロードすれば良さそうですが、以下の理由から不十分です。プログラムが直接システムコールを呼ぶ。C のライブラリ関数自体にバリエーションがある。対象プログラム自身が他のライブラリをプリロードする必要がある。とのことです。
ということでどうするかというと
ざっくりですが、記録と再生のどちらもオーバーヘッドは 2 倍以下に収まることが多いように見えます。メモリオーバーヘッドに関しては現実的には無視できる程度のようです。
どちらかというと実装力!という論文だとは思いますが実際にすでに大きなインパクトを与えているソフトウェアなので言うことはあまりない気もします。非常に良い仕事だと思います。