リクルートの中古車情報サイト「カーセンサーnet」を全面リニューアルした体験を基に、大規模サイトの性能改善作業の実態をレポートする。第1回第2回で行ったNFSとApacheの設定変更、PHPアプリケーションの見直しによって、性能は劇的に向上した。しかしその後、どうしても性能が伸びない。第3回での調査で、Linuxカーネルに原因があるらしいことがわかってきた。

 カーネルソースがあるディレクトリーに移動して、変数名(kernel_sem)を含むファイルを調べた。すると「lib/kernel_lock.c」というファイルの中で「kernel_sem」が定義されていた。冒頭を読むと、「This is the traditional BKL - big kernel lock」とある。直訳すれば「巨大なカーネルロック」。これは何なのだろうか。コメントを追っていくと、「古い方式」であり「新しいコードでは使うな」などと書いてある。いかにも、これが怪しい。

図9●セマフォーを獲得する関数「lock_kernel」
図9●セマフォーを獲得する関数「lock_kernel」
[画像のクリックで拡大表示]
図10●マルチCPU環境におけるBKL(Big Kernel Lock)の挙動
図10●マルチCPU環境におけるBKL(Big Kernel Lock)の挙動
[画像のクリックで拡大表示]

 次に__downを呼び出している箇所を調べた。出てきたのが「lock_kernel」という関数だ(図9)。「Getting the big kernel semaphore.」のコメントにある通り、どうやらここで、カーネルセマフォーであるkernel_semを獲得している。

 さらに詳細な解析に入る前に、BKLについて調べた。BKLは、対称型マルチプロセッシング(SMP*1)システムにおいて、同時実行制御のために使われるシステムグローバルなロックだった。BKLによって保護されているカーネル処理は、BKLを確保できたCPUだけが実行できる。BKLを獲得できなかったCPUは、獲得できるまで待たなければならない(図10)。これではCPU(コア)数が増えてもBKLによって保護されているカーネル処理の並列度が上がらず性能が向上しない。やはり、これが性能劣化の原因である可能性が高そうだ。

 後になって分かってきたことだが、BKLの問題は要するに、システム全体でただ1つのロックを取り合うことである。システムの機能単位や共有リソースごとにロックを用意すれば問題は改善する。カーセンサーnetが利用するLinuxディストリビューション「RHEL」(Red Hat Enterprise Linux)の母体となっているLinuxカーネルプロジェクト*2では、パフォーマンス劣化の原因となるBKL自体をソースから取り除く取り組みは続けられていた*3。ただしカーセンサーnetが使うRHEL5系には、まだBKLが残っていた。