今回、Gentoo の GNOME デスクトップを構築する際にハマったことを紹介します。
私は普段から Arch Linux では GNOME を使用しているのですが、前回、 Gentoo の Systemd-boot ではハマったことを紹介した際に Gentoo を使用し始めたと公言しました。
コンソール画面で作業するのもいいですが、やはりここはデスクトップ用途で普段使いをしたいため、デスクトップの導入は必須です。
Linux ではいろいろなデスクトップがはびこっています。
その中で、自分も使い慣れているし、人気No.1である GNOME を使いたいと思ったわけです。
(ちなみに KDE も使っている(ただし Unity 、お前はだめだ))
ぱぱっと USE フラグを設定し、 emerge をしました。
やはりデスクトップ環境を整えるには、たくさんのパッケージをコンパイルしなければならず、その数およそ400個にも及びました。
もうそのような数になると、バイナリパッケージとコンパイルではかかる時間が太陽と地球ぐらいの差が出ます。(マシンパワーにもよるがバイナリパッケージでは約10〜30分程度、コンパイルにかかる時間は4〜12時間程度(←「時間」だよ「時間」))
その中で一際目立つのは net-libs/webkit-gtk 。実はこれ、ちゃちい PC でコンパイルしようとするならば6時間以上かかります。(←もう草しか生えないわ!)
驚くことにこいつのコンパイルとなるとメモリをばかさか食う大食漢ですw
今回はこいつのコンパイルを取り扱おうと思います。
では、私の PC の WebKit のビルドに関わる大まかなスペックを紹介します。
Intel Core i7-4700MQ (4コア/8スレッド)
8GB(DDR3L SDRAM/SO-DIMM 8GB)
これで最初、 gnome-base/gnome グループをコンパイルしていました。
難なく完了すると思いましたが、 net-libs/webkit-gtk になってしばらくすると状況は一転、進んでいるのか止まっているのかわからない状況になりました。
どういうことかというと、カーソルは点滅、ただし、コンパイルしているソースの部分は変わらず、 tty 切り替えが反応せず。
といった状況でした。
しばらく待っていると、赤い「*」とコンパイル失敗を示す文字が現れました。
最初は全く状況がわからず、ずっと悩んでいたのですが、ある日、私の使っている他のディストリビューションでコンパイルを行ってみてはどうかという結論にいたり、そこでエラーの再現を行うことにしました。
そこで使ったのが Arch Linux です。
Arch Linux で「virtual memory exhausted: Cannot allocate memory」というエラーが出たので、メモリ 8GB では余裕で枯渇してしまうことがわかり、メモリ問題はスワップファイル作成で解決しようと思いましたが、ここでまた問題が発生したのです。
なんと、私の使っているファイルシステムが btrfs だったのです。
代わりの方法として、 /dev/loop* を一時的なスワップファイルとして使うことにしました。
とりあえず、 /dev/loop0 を一時的なスワップファイルとして使用します。
まず適当なディレクトリ(ただし / や、 /dev/sda* は除く)に /dev/zero デバイスの情報を書き込みます。
dd bs=1M if=/dev/zero of=/swap count=16384
これで、 16GB のスワップファイルのもとになるディレクトリが完成しました。
そしてそれを /dev/loop0 にマウントしていきます。
losetup /dev/loop0 /swap
そして /dev/loop0 にスワップファイルを生成します。
mkswap /dev/loop0
swapon /dev/loop0
これで、 /dev/loop0 にスワップファイルを生成できました
そしてこれで WebKit のコンパイルに再挑戦しました。
ですが、エラーは出なくなったものの、今度はスワップファイルを作成したときよりも長時間進まなくなってしまいました。
tty 切り替えもうまく行かなかったので、もしやコンパイル中に PC がフリーズしているのではないかと思いました。
よく PC がフリーズする原因は、 CPU 使用率が何らかの原因で 100% になる。ということで起きます(一例)。
今回過剰な並列コンパイルが原因と見て、並列コンパイル数を 9→5 に変更してみました。
そうしたら、普通にコンパイルが完了し、通常通り使えるようになりました。
最後に、今回の Ninja のエラーは2つの要因で起きていることがわかりました。
1つ目
swap — [不定]
歴史的に、物理メモリの容量の2倍のスワップパーティションを用意するべきという一般法則がありました。より大容量のメモリがコンピュータに積まれるようになり、この法則はすでに現状にあてはまりません。メモリが 512 MB 以下のマシンでは、2倍ルールが基本的に適合します。大容量のメモリ(1024MB 以上)を積んでいるときは、スワップパーティションは小さく、または作らなくてもかまわないでしょう。2GB 以上の物理 RAM を持っているなら、スワップパーティションがないほうが一般的に良いパフォーマンスを発揮すると思われます。
このように 2GB の RAM を積んでいるマシンでは、スワップパーティションを作らない方がいいパフォーマンスを発揮できると言われています。これは正しいことです。
ディスクの IOPS などを考えると、ディスクに退避させるより、メモリ上で完結させるほうが遥かに高速です。
ですが、メモリのデータの収容能力を超えて処理したらどうでしょう?
仕方なくディスクに退避させるしか方法はないわけです。
そのためにスワップパーティションを作れというのかというとそうも行きません。
そのためだけに作るのはいかがなものかと思います。
だから、スワップファイルという仕組みが存在します。
結局何が言いたいのかというと、いくら物理メモリが多くても、スワップが必要になることはあるということで、今回がその例です。
2つ目
MAKEOPTS変数は、パッケージのインストール時にどれだけ並行してコンパルを走らせるかを定義します。CPU数(コア数)プラス1を選択するのがよい選択とされていますが、ガイドラインは常に最良とは限りません。
同時コンパイルを可能にする MAKEOPTS 変数ですが、普段は倫理コア数(スレッド数)+1が最良と言われていますが、書かれている通りこれが最良とは限りません。
用途に応じて増やす or 減らすなどの判断をすることのほうが大切なわけです。
パッケージによっては、ガイドラインより増やしたほうがより早く処理ができるでしょう。逆にガイドラインよりも減らしたほうがいい場合もあります。
今回の例でもありますが、極端に増やした場合、 CPU の処理が間に合わず、フリーズして失敗することもあります。
今回のことについては、スワップはときに重要になることと、並列コンパイルはコンパイルするパッケージ毎に臨機応変に変えていくことが理想です。
しかし、並列コンパイルをパッケージ毎に変えるというのは、そこそこ現実味がないので、ガイドラインで定められているのだと思います。
みなさんもこういったことにはくれぐれも気をつけていただきたいものです。
今回はここまでにします。
では、また。