彷徨えるフジワラ

年がら年中さまよってます

Mercurial 開発環境におけるテストセット実行性能の改善

先に結論を書いておきますが、要するに:

利用可能な CPU コア数を増やし、高並列に実施すれば、早く終わる

という、至極平凡な話です(笑)。

事の始まり

先日、自分の投函したパッチに関して、マスターリポジトリに変更が取り込まれる寸前に、ちょっとした間違いに気付いたので:

まだ修正が間に合うなら、正式取り込みはちょっと待ってくれない?
数10分以内に、修正版のテストを実施して、再投函するから。

という意図のメールを開発向け ML に投函したところ:

ちょ、え、まじ?テストが2分で完走しない環境なの? (意訳)

という返信をもらいました。

私の Mercurial 開発のメイン環境は、VirtualBox on 64bit Windows7 上で稼動する 64bit debian 環境なのですが、仮想環境ホスト側は、メモリこそ当時としては破格の 16GB を搭載しているものの、静穏・省電力を重視して AMD Phenom II X4 905e を使用してるので、2009年の導入から5年程が経過した今となっては、流石に非力さを隠せません。

また、以前(3年程前?)確認した際には、15分程度で完走していた(と記憶している) Mercurial のテストセットも、現時点で改めて確認してみたら、完走に30分を要するまでに肥大していました…… orz

件の返信のような「2分で完走」は無理にしても、流石にテスト完走に30分掛かるのはまずいので、開発環境における Mercurial テストセットの実行性能改善に着手することにしました。
ちなみに、Mercurial のテストセットは、Mercurialソースコードを入手した上で、ソースコードツリーのルートディレクトリで "make tests" することにより実行できます。網羅的に実施しようとするなら、一般的な開発系ツール (Python 環境含む) 以外に:

  • OpenSSL python binding ライブラリ
  • docutils ライブラリ
  • pygments ライブラリ
  • pyflakes ライブラリ
  • CVS
  • Subversion python binding ライブラリ
  • Git
  • Bazaar

あたりも導入しておいた方が良いでしょう。

改善の方向性

さて、改善するにあたってボトルネックを調べてみたのですが……清々しいまでに CPU ボトルネックでした…… orz

vmstat 等でリソース消費状況を確認しても、基本的に I/O wait での待ちは殆ど発生していません。

試しに、Linux 環境で "export TMPDIR=/dev/shm" 指定を使うことで、テストデータ等の書き出し先をメモリデバイス上に変更してみたりもしたのですが、テストセットの完走に要する時間には、変化が見られませんでした。

メモリ枯渇の兆候も見られませんし、実際にメモリ割り当てを大幅に増やしても、所要時間は変わりませんでした。

こうなると、CPU 自体の性能向上 (scale-up) か、複数 CPU 割り当て+並列実行 (scale-out) しか打つ手はありません。

幸い Mercurial のテストセットでは、"make TESTFLAG='-jN' tests" とすることで、並列度 N で実行させることが出来ますし、稼働環境は複数CPUコアが利用可能なので、scale-out の方向で行くのが良さそうです。

Linux on Phenom II X4 905e での計測結果

まずはメインで使用している以下の環境 (但し VirtualBox による仮想環境) で、利用可能 CPU 数/並列度の増加による所要時間の変化を計測してみました。





利用可能CPU
並列度 所要時間 対「1並列」比率
1 1 約30分 100%
2 2 約15分 50%
3 3 約10分 33%
3 4 約10分 33%

利用可能 CPU 数/並列度の増加と性能向上が、見事なまでに一致しています。CPU x3 上で 3 並列 → 4 並列による性能向上が見られないことからも、殆どが演算処理で消費されているのでしょうね。

なお、仮想環境に3コア割り当てた状態で、Mercurial のテストセットを並列度3で実行すると、ホスト側処理が残り1つのコアに集中するため、ホスト側での監視では、CPU使用率がほぼ 100% を維持し続けることになります。

利用可能な物理4コアの全てを仮想環境に割り当ててしまうと、ホスト側がにっちもさっちも行かなくなってしまうであろうことは、火を見るよりも明らかなので、私の環境では3コア割り当てが上限でしょうねぇ。

これ以上の改善としては、同一ソケット規格で使用可能な Phenom II X6 へのアップグレード+割り当て CPU 数の増加、という手もありますが、現状 Phenom II X6 は中古市場でしか入手出来ないことを考えると、個人的には二の足を踏まざるを得ない選択肢と言えます。中古の AMD 6 コア CPU なんて、絶対酷使されているに決まっていますし(笑)

Mac OS X on Core i5 2415M での計測結果

case-insensitiveファイルシステム上での動作確認に使用している、Mac mini 環境でも所要時間を計測してみました。




利用可能スレッド
並列度 所要時間 対「1並列」比率
4 1 約53分 100%
2 約30分 56.6%
4 約22分 41.5%

並列度増加がリニアに効いている場合、並列度 4 の対「1並列」比率は 32% (0.566 * 0.566 = 0.320) 程度でなければならないのですが、実測値では 41.5% に留まっており、並列度 2 → 4 のインパクトが、並列度 1 → 2 のインパクトには及ばないことがわかります。

物理2コア+Hyper Threading により、「4 スレッド」を謳う Core i5 2415M ですが、整数演算偏重の処理では、やはり「物理コアを増やしてナンボ」ということでしょうか?(笑)

とは言え、見せ掛けの CPU 数増加でも、「無いよりはマシ」であるのも確かなのですけどね。

Linux on Core i5 2410M での計測結果

比較のために、先述の Mac mini と同等程度の CPU を使用しているノートPC (64bit Windows7) でも、VirtualBox 環境上での実行性能を計測してみました。




利用可能CPU
並列度 所要時間 対「1並列」比率
1 1 約25分 100%
2 2 約14分 56%
先述した Mac OS X が稼動している Core i5 2415M (2.3GHz) と、上記の Linux が稼動している Core i5 2410M (2.3GHz) では、純粋な CPU 性能はほぼ同等 (むしろ前者の方が少しだけ高性能) の筈なのですが、私の計測した範囲では、Mac OS X 上での 4 並列実行でも、Linux (on VirtualBox) 上での 2 並列実行に及びませんでした。 Mac OS X 環境では、最初に計測した後で (1) HDD → SSD への換装、(2) HFS+ のジャーナル機能の停止、(3) 所有権設定情報の修復、(4) SSD への TRIM 有効化等々、I/O 周りに影響すると思われる一連の対処を一通り行っても、テスト完走に要する時間に変化はありませんでしたので、I/O オーバヘッドによる劣化では無さそうです。 Linux 側が「仮想化環境での実行」というハンデを負った上で、なお上記のような明確な性能差があるのだとしたら、この差は「Mac OS XLinux の実行効率の差」ということでしょうか。 とりあえず現状では、「fork + execveLinux と比較して圧倒的に遅い」点が、所要時間差の主要因の1つと思われます。 read/write や、ディレクトリ要素操作等の性能比較は、別途条件を揃えて取り組んでみたいところですねぇ……

おまけ

さくらの VPS を契約している知人に頼んで、最廉価プラン (1Gプラン) 環境の Linux 上でも、所要時間を計測してもらったのですが、概ね Core i5 2415M 上の Mac OS X と同等程度の性能とのことでした。

手元に同等性能の機材がない状況であれば、月々 1,008 円の維持費で済むというのは、非常に魅力的ですが、私の場合は同等(or それ以上の)性能の機材が既にあるので、少なくとも「Mercurial のテスト環境の改善」目的では、積極的に導入する気にはならない性能ですねぇ……

より高性能な環境を調達するとなると、個人的には以下のような感じでしょうか?

  • さくらの VPS の、より上位のプランの利用
    ⇒ 数年単位で考えると、手元のハードを新調したくなる価格(笑)
  • 高性能 CPU を時間貸ししてくれる VPS ベンダーの利用
    インスタンスの on/off が面倒そうだが、検討する価値はあるかも?

ちなみに、件の返信をくれた Pierre-Yves 氏は、別のメールで:

64 コア Power7 プロセッサ上で 90 並列実行+メモリデバイス使用なら、1分49秒でテストを完走できるよ

であることを言及してました。

そりゃー、3並列で10分掛かる処理も、それだけ並列実行できれば、所要時間は2分を切るよね(笑)