BSD界隈四方山話

第28回FreeBSDビルドを高速化する2つのオプション登場

ビルド時間を短縮化する2つのオプション

2015年11月6日(協定世界時)と2015年11月8日(協定世界時)にFreeBSDの開発者であるBryan Drewery氏によってCURRENTに対して次の2つのコミットが実施されました。ビルド時間を15%~65%ほど高速化するオプションの導入です。ビルドワールドとビルドカーネルの双方に適用できます。

1つ目のコミットは広く効果が期待できるもので、しばらく試験を重ねたのち、デフォルトの機能として有効化されるものとみられます。2つ目の機能はサードパーティ製のソフトウェア(ccache)を使うためデフォルトで有効化されることはないように思えますが、繰り返しビルドするようなケースで大幅な高速化が期待できる機能ですので、覚えておいて損はないと思います。

WITH_FAST_DEPENDのしくみ

2015年11月6日(協定世界時)に追加されたのは「WITH_FAST_DEPEND」オプションです。このオプションを指定すると、ビルドの依存関係データの生成にmkdep(1)ではなく、コンパイラの機能を使うようになります。この変更によるビルド時間の短縮は、コメントに記載されている内容によればビルドワールド(make buildworld)で16%の短縮、ビルドカーネル(make buildkernel)で35%の短縮とあります。

FreeBSDではmake dependの段階でmkdep(1)コマンドを実行してビルドの依存関係データを生成しています。ビルドの依存関係データは対象となるソースコードが置かれているディレクトリに.dependという名前のファイルとして出力されます。make buildworldやmake buildkernelを実行したあとに/usr/obj/でfind . -name .dependのようにファイルを探してみれば、どういったデータが出力されているのかがよくわかるでしょう。

今回追加された機能はWITH_FAST_DEPEND=yesを指定してビルドを行った場合、依存関係データの出力にmkdep(1)を使うのではなく、cc(1)に-MD -MF -MTオプションを指定してコンパイル時に依存関係データを出力するようにする、というものです。この機能を有効にすることでプリプロセッサがビルド毎に2回実行されることを防ぐことになり、ビルド時間が短縮することになると説明されています。

ビルド時に依存関係データを出力する機能はGCC 3.0には導入されていましたので、かなり古い機能です。FreeBSD 10以降にシステムのデフォルトコンパイラであるLLVM Clangも同様の機能をサポートしていますので、今回はLLVM Clangのこの機能を使って高速ビルドを実現したことになります。

今回の追加では同機能はデフォルトでは無効化されていますが、しばらく様子をみたのちデフォルトで有効化する意向であることが説明にあります。最終的にはカーネルとシステムのビルドのみならず、Ports Collectionのビルドにおいてもこの機能が適用されていくようです。

WITH_FAST_DEPENDベンチマーク

コミットにはWITH_FAST_DEPENDオプションを指定した場合と指定しなかった場合のビルドワールドとビルドカーネルの時間の計測結果が掲載されています。試験に使われたハードウェアおよびカーネル、ビルドオプションは次のとおりです。

  • CPU:2way Intel Xeon L5520@2.27GHz(16論理コア)
  • メモリ:76Gバイト
  • ディスク:ZFS 3-wayミラー(SSD L2ARC/LOG使用)
  • カーネル:WITNESSオプション含む
  • ビルドオプション(x):-j20 WITH_LLDB=yes WITH_DEBUG_FILES=yes
  • ビルドオプション(+):-j20 WITH_LLDB=yes WITH_DEBUG_FILES=yes WITH_FAST_DEPEND=yes
ビルドワールド比較(実行結果)
  x buildworld-before
  + buildworld-fastdep
  +-------------------------------------------------------------------------------+
  |+                                                                              |
  |+                                                                              |
  |+                                                                       xx    x|
  |                                                                       |_MA___||
  |A                                                                              |
  +-------------------------------------------------------------------------------+
      N           Min           Max        Median           Avg        Stddev
  x   3       3744.13       3794.31       3752.25     3763.5633     26.935139
  +   3       3153.34       3155.16        3154.2     3154.2333    0.91045776
  Difference at 95.0% confidence
          -609.33 +/- 43.1943
          -16.1902% +/- 1.1477%
          (Student's t, pooled s = 19.0569)
ビルドカーネル比較(実行結果)
  x buildkernel-before
  + buildkernel-fastdep
  +-------------------------------------------------------------------------------+
  |+                                                                            x |
  |++                                                                           xx|
  |                                                                             A||
  |A|                                                                             |
  +-------------------------------------------------------------------------------+
      N           Min           Max        Median           Avg        Stddev
  x   3        571.57        573.94        571.79     572.43333     1.3094401
  +   3        369.12        370.57         369.3     369.66333    0.79033748
  Difference at 95.0% confidence
          -202.77 +/- 2.45131
          -35.4225% +/- 0.428227%
          (Student's t, pooled s = 1.0815)

説明どおり、ビルドワールドで16%ほど、ビルドカーネルで35%ほど高速化していることが確認できます。

WITH_CCACHE_BUILDのしくみ

WITH_FAST_DEPENDオプションの追加から2日後となる2015年11月8日(協定世界時)には、同じくBryan Drewery氏によってWITH_CCACHE_BUILDというオプションが追加されました。これはビルドにccache(1)を利用するためのオプションです。ccache (devel/ccache)がインストールされていればとくに設定することなく、ccache(1)を使ったビルドが有効になります。

カーネルを書き換えるような開発をしている場合、一部のソースコードをちょっと変更してはビルドして結果を試すといった作業を繰り返すことがあります。この場合、依存関係などからクリーンなビルドが実施されないといった状況を避けるために-DNO_CLEANを指定せずに、毎回生成したファイルを削除してビルドを行うことがあります。

ccache(1)はこういったケースでキャッシュを効かせることでビルド時間の短縮を図るといったもので、繰り返しビルドを実施するようなケースでビルド時間の短縮が期待できます。この高速化機能は先ほどのWITH_FAST_DEPENDと相乗効果が期待でき、最大で64%ほどの高速化が観測できたとしています。

WITH_CCACHE_BUILDベンチマーク

WITH_FAST_DEPENDと同じくこちらもビルドワールドとビルドカーネルの比較結果が掲載されています。使用しているハードウェアはWITH_FAST_DEPENDと同じです。比較には通常のビルド、キャッシュが存在していない状態でWITH_CCACHE_BUILDを指定したビルド、キャッシュが存在しておりフルでキャッシュが効く状態でのWITH_CCACHE_BUILDを指定したビルド、フルでキャッシュが効いた状態のWITH_CCACHE_BUILDにさらにWITH_FAST_DEPENDを指定したビルド、WITH_FAST_DEPENDのみを指定したビルド、が取り上げられています。

キャッシュが効いていない状態でWITH_CCACHE_BUILDを指定すると逆にビルド時間が増えていますが、キャッシュが有効になった状態ではビルド時間の短縮が確認できます。

  • ビルドオプション(x):-j20 with_lldb=yes with_debug_files=yes
  • ビルドオプション(+):-j20 with_lldb=yes with_debug_files=yes with_ccache_build=yes
  • ビルドオプション(*):-j20 with_lldb=yes with_debug_files=yes with_ccache_build=yes
  • ビルドオプション(%):-j20 with_lldb=yes with_debug_files=yes with_ccache_build=yes with_fast_depend=yes
  • ビルドオプション(#):-j20 with_lldb=yes with_debug_files=yes with_fast_depend=yes
ビルドワールド比較(実行結果)
  x buildworld-before
  + buildworld-ccache-empty
  * buildworld-ccache-full
  % buildworld-ccache-full-fastdep
  # buildworld-fastdep
  +-------------------------------------------------------------------------------+
  |%            *                               #                                +|
  |%            *                               #                                +|
  |%            *                               #             xxx                +|
  |                                                           |A                  |
  |                                                                              A|
  |             A                                                                 |
  |A                                                                              |
  |                                             A                                 |
  +-------------------------------------------------------------------------------+
      N           Min           Max        Median           Avg        Stddev
  x   3       3744.13       3794.31       3752.25     3763.5633     26.935139
  +   3          4519       4525.04       4520.73       4521.59     3.1104823
  Difference at 95.0% confidence
          758.027 +/- 43.4565
          20.1412% +/- 1.15466%
          (Student's t, pooled s = 19.1726)
  *   3       1823.08        1827.2       1825.62        1825.3     2.0785572
  Difference at 95.0% confidence
          -1938.26 +/- 43.298
          -51.5007% +/- 1.15045%
          (Student's t, pooled s = 19.1026)
  %   3       1266.96       1279.37       1270.47     1272.2667     6.3971113
  Difference at 95.0% confidence
          -2491.3 +/- 44.3704
          -66.1952% +/- 1.17895%
          (Student's t, pooled s = 19.5758)
  #   3       3153.34       3155.16        3154.2     3154.2333    0.91045776
  Difference at 95.0% confidence
          -609.33 +/- 43.1943
          -16.1902% +/- 1.1477%
          (Student's t, pooled s = 19.0569)

ビルドワールドではキャッシュが効いた状態で51%の高速化、これにさらにWITH_FAST_DEPENDが加わると66%の高速化が確認できます。

  • ビルドオプション(x):-j20 with_lldb=yes with_debug_files=yes
  • ビルドオプション(+):-j20 with_lldb=yes with_debug_files=yes with_ccache_build=yes
  • ビルドオプション(*):-j20 with_lldb=yes with_debug_files=yes with_ccache_build=yes
  • ビルドオプション(%):-j20 with_lldb=yes with_debug_files=yes with_ccache_build=yes
  • ビルドオプション(#):-j20 with_lldb=yes with_debug_files=yes with_ccache_build=yes with_fast_depend=yes
  • ビルドオプション(@):-j20 with_lldb=yes with_debug_files=yes with_fast_depend=yes
ビルドカーネル比較(実行結果)
  x buildkernel-before
  + buildkernel-ccache-empty
  * buildkernel-ccache-empty-fastdep
  % buildkernel-ccache-full
  # buildkernel-ccache-full-fastdep
  @ buildkernel-fastdep
  +-------------------------------------------------------------------------------+
  |#                        @   %                  *                              |
  |#                        @   %                  *     x                      + |
  |#                        @   %                  *     xx                     ++|
  |                                                      MA                       |
  |                                                                             MA|
  |                                                A                              |
  |                             A                                                 |
  |A                                                                              |
  |                         A                                                     |
  +-------------------------------------------------------------------------------+
      N           Min           Max        Median           Avg        Stddev
  x   3        571.57        573.94        571.79     572.43333     1.3094401
  +   3        727.97        731.91        728.06     729.31333     2.2492295
  Difference at 95.0% confidence
          156.88 +/- 4.17129
          27.4058% +/- 0.728695%
          (Student's t, pooled s = 1.84034)
  *   3         527.1        528.29        528.08     527.82333    0.63516402
  Difference at 95.0% confidence
          -44.61 +/- 2.33254
          -7.79305% +/- 0.407478%
          (Student's t, pooled s = 1.02909)
  %   3         400.4        401.05        400.62        400.69     0.3306055
  Difference at 95.0% confidence
          -171.743 +/- 2.16453
          -30.0023% +/- 0.378128%
          (Student's t, pooled s = 0.954969)
  #   3        201.94        203.34        202.28        202.52    0.73020545
  Difference at 95.0% confidence
          -369.913 +/- 2.40293
          -64.6212% +/- 0.419774%
          (Student's t, pooled s = 1.06015)
  @   3        369.12        370.57         369.3     369.66333    0.79033748
  Difference at 95.0% confidence
          -202.77 +/- 2.45131
          -35.4225% +/- 0.428227%
          (Student's t, pooled s = 1.0815)

ビルドカーネルでも同様の傾向を見せています。キャッシュが効いた状態では30%の高速化、キャッシュにさらにWITH_FAST_DEPENDを効かせた状態で64%の高速化です。WITH_FAST_DEPENDと合わせて効果的なビルド時間の短縮が実現できていることがわかります。

知って得するオプション

ccache(1)を使ってビルドワールドやビルドカーネルの時間を短縮することはこれまでもできましたし、使っている開発者はずっと使っているでしょう。今回のコミットが注目されるのは、デフォルトのオプションとして追加されたので、ccache(1)の利用が簡単になったということにあるでしょう。

WITH_FAST_DEPENDの方もとくに問題はないように思えますし、そう遠くない段階でデフォルト化するのではないかと思います。FreeBSD Updateやpkg(8)の登場でシステムやアプリケーションをビルドする機会は減っているかもしれませんが、カスタマズしたカーネルを使う必要があるなど、その必要性は今でも少なくないと思います。このオプションはビルド時間の短縮につながりますので、ぜひいちど試してみてください。

コミットされたのがCURRENTですので、リリースに反映されるのはFreeBSD 11.0-RELEASEおよびFreeBSD 10.3-RELEASE以降になると思います。

FreeBSD勉強会 告知

第46回 11月20日(金)19:00~ The Design and Implementation of the FreeBSD Operating System (2nd Edition) 読書会 第11回目 P.121 The scheduler implements round-robin…~

The Design and Implementation of the FreeBSD Operating System (2nd Edition)の読書会です。読書会11回目の今回はハードカバーでP.121からです。D&I本がどういった本なのか読んでみたいという方、お気軽にご参加ください。参加申請はこちらから。

第47回 12月22日(火)19:00~ ライトニングトーク×FreeBSD忘年会’15!

今やっていることがある、実はこんな感じで運用している、困っていることがあるので助け求むなど、FreeBSDに関することを5分から10分程度にまとめて、その時発表したい方が発表する「ライトニングトーク×FreeBSD忘年会'15!」を開催します。

後藤からは発表の冒頭、5分~10分くらいでbhyveを使った仮想環境構築のデモンストレーションを行います。CentOSかOpenBSDあたりをon bhyveで使う方法をご紹介します。ひとりあたりの発表時間は、全体の発表人数を見つつ当割でいきます。時間に余裕があれば現場で飛び込みライトニングトークも大歓迎です。参加申請はこちらから。

おすすめ記事

記事・ニュース一覧