#:g1: SBCL 1.4.12のfold-identical-codeを試してみた

Posted 2018-09-29 19:35:02 GMT

今月も月末にSBCLの新バージョンがリリースされましたが、リリースノートに、

とあり、どんな機能か気になったので調べてみました。

fold-identical-code

ちょっと調べても説明もなく良く分からなかったので、githubのコミットログを眺めましたが、fold-identical-codeとかいうのが、その機能のようです。

fold-identical-code を使ってみる

どう使うのかは、良く分かりませんが、

fold-identical-codeが定義されているsrc/code/icf.lisp

;;;; Identical Code Folding (similar to what might be done by a C linker)

とあるのでコードサイズの縮小あたりが狙いなのかもしれません。

とりあえず、下記のような同じ内容の関数を定義してみてからfold-identical-codeを実行してみると、

(progn
  (defun foo (x) (+ 42 x))
  (defun bar (x) (+ 42 x))
  (defun baz (x) (+ 42 x)))

(fold-identical-code :aggressive t :print t)

以下のようにずらっと結果が表示されますが、

#<code id=154F2 [1] baz {53FD93CF}> = #<code id=154F0 [1] foo {53FD92AF}>
#<code id=154F1 [1] bar {53FD933F}> = #<code id=154F0 [1] foo {53FD92AF}>

barbazfooにまとめられているようです。

使用メモリの削減具合を確認するためにイメージをダンプしてみましたが、135MiBのイメージが、ダンプ時にfold-identical-codeを実行してからダンプすると、134MiBに縮みました。

1%も縮まっていない感じですが、C++等のリンカの最適化を解説しているページによると、重複の削除によって1〜2%縮むと書いてあるものが多いようなので、そんなものなのでしょう。

むすび

今の所ドキュメントは整備されておらず、src/code/icf.lispsrc/code/icf.lispを読むしかない感じですが、今後整備されていくと思うので期待して待ちたいです。

ちなみに当初自分が期待していたのは、disassembleした時のインストラクションが同一になるかどうか確かめるユーティリティだったのですが、下記のようにfold-identical-codeの部品であるsb-vm::code-equivalent-pを使って判定できるようです。

(defun fun-code-equivalent-p (f g)
  (sb-vm::code-equivalent-p (list (sb-c::fun-code-header f))
                            (list (sb-c::fun-code-header g))))

(fun-code-equivalent-p #'foo #'bar) ;=> t

ごくたまに欲しい時があって、disassemble関数の中身を使って自作していましたが、sb-vm::code-equivalent-pを使った方が正確に判定できるようなので、今後はこちらを使おうかなと思っています。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus