Raspberry Pi とマインクラフト・サーバーと、時々オーバークロック
先日入手した、4つのCPUコアを持つARMプロセッサー搭載のRaspberry Pi 2 Model B(2015年7月段階では最新モデル)。
これ使ってマインクラフト・サーバーを立てるとしたら、どういうものが出来るのか、ってことでいろいろと試してみた。
最終ゴールは「自宅の無線LANに、プレイヤー最大3人(自分+娘二人)がいつでも遊べるマインクラフト・サーバーを常設する」というもの。
結論から先に言うと・・・
制約はあるけど、ある程度、ゴールは達成できた。
ただ、ゲームのモードやプレイスタイルによって要求は変わってくるので一概に「出来る・出来ない」の判定は避けたい。ただひとつ言えることは、ほんの数千円でいろいろと試行錯誤したりして楽しくPiと遊べるし、子供も巻き込んだりすればIT教育としての効果もあるかな、と思ったりもする。
使用したハードウェア
無線LANルーター
Piを無線LANルーターの空いてるLANポートの一つにLANケーブルで繋いでネットに乗せたので。PiのUSBに無線LANアダプターを付けることも可能だけど、サーバーとして使うなら有線の方がスループットが高くてなおかつ安定してるので望ましい。
Raspberry Pi 2 Model B
主役のSoCデバイス。このモデルはメモリーが1GB。メモリー容量はマインクラフト・サーバーをホストする上で重要。ネットではマインクラフト・サーバーには1GBを割り当てているのをよくみる。初代のPiでメモリーが512MBのモデルがあるが、かなりきついんではないだろうか。
加えてこのARMのCPUにはコアが四つある。後述するが、Javaランライムのガーベッジコレクターの作業をバックグラウンド・スレッドに割り当てるオプションがあるので、おそらくマルチコアの恩恵を期待できると思う(検証はしていない)。
Micro SD card 容量8GB
Piのブートメディアおよびメインのストレージとして使用。容量は4GBでもいけるかもしれないけど、私は8GBにした。SDスピードクラスはClass6。Class10を買おうかと思ったけどいくつかのベンチマーク記事で、あんまり変わらないっぽかったのでちょっとお金をセーブした。
電源アダプター
PiはUSB電源も対応しているけど、後述する「オーバークロック」等の最適化で安定した電源が必要になるんで、しっかりと120Vのアウトレットから電源アダプターで電力供給することに。
Ethernet ケーブル
Piを無線LANルーターに繋げるため。これはそこら辺に転がってるやつなら何でもいい。Ethernetケーブルは配線が微妙に異なるものもある(あった)けど、最近のインターフェイスは勝手に調節してくれるんで、気にしなくてもOK。
ノートパソコン
これは念のためにリストに加えておく。自分はPiの操作はすべてノートパソコンから遠隔でSSHでやったので必要だったけど、普通にPiをHDMI出力でモニターに繋いでキーボード&マウスで操作、なら必要ない。(でも結局はクライエントとして必要だね・・)
使用したソフトウェアのリスト
Raspbian
使用したPi2のオペレーティングシステム。UbuntuやWindows10(!)なんかも使えるけど、取りあえずなるべく純正っぽいもので。
(Java Runtime)
これはRaspbianのOSイメージにすでにオラクルのランタイムが入ってた。OpenJDKとかでもOKだけど、今回は素直にプリインストールのJavaを使用。
Spigot Minecraft Mode Server
公式のマインクラフト・サーバー(バニラ風味)ではなく、Modの中でもパフォーマンスが優れているというSpigotを使用。実は最初、バニラ・サーバーを使って最適化を試みたんだけど、後述するオバークロッキングをもってしてもサーバー処理が追いつかないことがよくあって、Spigotに代えてみたら安定感が増した、という経緯があった。
PuTTY
Windows側からSSHするのに使う一般的なツール。Piを直接操作するなら必要ない。
git
これはSpigotのソースをダウンロードするのに使う。わざわざ上げるまでもないかもしれないけど・・・
ステップ1ー SDカードにRaspbianイメージをインストールする
これは「raspbian SD card インストール」でググると、詳しく手順を解説した記事がわんさと出てくる。例えばこれなど。
Raspbianを入れたSDカードが作成できたら次のステップへ。
ステップ2-PiをSSHで遠隔操作できる環境を整える
これは別の記事として書いてあるのでそちらを参照してください。
watanabe-tsuyoshi.hatenablog.com
このステップで、準備したハードウェア全てを使うことになる。
ステップ3-Spigot サーバーをインストールする
これも別に記事として書いてあるのでそちらを参照してください。
watanabe-tsuyoshi.hatenablog.com
一つだけ追記しておく。
使用したSDカードの容量は8GBだけど、OSの初期設定では2GB程度のストレージとして設定されている。何もせずにSpigotのビルドしたら「容量不足」で失敗した(厳密にはビルドは成功したけれど、コピーする段階でエラーになった)。
容量を目いっぱい使えるように設定して、再度ビルドしたら成功した。
SDカード容量分のストレージサイズにするには、まずPiのコンソールから
というコマンドを与える。
すると、下のような画面が開く。(この画面と、raspi-config はこれから何度も登場する)
この一番上の「1 Expand Filesystem」という項目を選ぶことで、SDカードの容量を最大限使用できるようにできる。再起動すると8GB近く利用できるようになった。
ステップ4-Piの最適化
Piをマインクラフト・サーバー専用として使うと決めたなら、いくつかの最適化をほどこすことが出来る。
具体的には
- 起動後に余計な資源を消費しないようにコンソールのログイン画面を初期画面にする設定
- 工場出荷時よりも高いクロック周波数に設定して処理能力を上げる(オーバークロッキング)
- GPUと共有するメモリーがCPUにより多く分配されるように設定
以下、その詳細と手順。
起動後にコンソールのログイン画面に行くようになっているか確認
これは工場出荷時のデフォルト設定なので、確認のみ。
Piの操作はSSHで行う予定なので、グラフィカルなデスクトップなどは必要ない。むしろその分メモリーなどの資源を使われるので好ましくない。
まず raspi-config コマンドで設定画面を開ける。
次に、項目3を選ぶ。
起動オプションで一番上のが選択されていればOK。
ちなみに、二つ目はGUIデスクトップが開く、三つ目はScratchという子供向けプログラミング環境が開く、というオプション。Piをそういう用途に使う場合は設定を変えるとよい。
次にオーバークロッキングの設定、だけどその前になぜマインクラフト・サーバーの最適化にオーバークロッキングが必要かの根拠を解説する。
マインクラフト・サーバーがもっとも必要とするのはCPU処理能力
CPUによる処理の遅延がサーバーにとっての最大の問題。これが起こると、プレイヤーはタイム・ラグを体感するようになり、プレイ体験が台無しになるばかりか、サーバーのクラッシュにも繋がる。
マインクラフト・サーバーでは毎秒20回ほどの「Tick」と呼ばれるイベントが発生し、そのたびにプレイヤーのそばの環境の変化を計算して結果を決定している。例えば牛が10頭いれば、そいつらがどこにどういう風に動くか、計算しないといけないし、クリーパーが爆発しようものなら、その爆発によって破壊されるブロックを計算しないといけない。TNTを何十個も仕掛けて一度に爆発させる(うちの娘たちが好んでやるマインクラフト内テロ)なんてものは処理機能がもっと高いマシンでも数秒かかることがある。
このTick処理は一回あたり1/20秒ほどしか時間が与えられてないわけで、このテンポにサーバーが着いていけなくなると、下のような警告が出てくる(これはバニラのサーバーの場合)
バニラサーバーでは実験中に何度もこのような状態になってクラッシュした。
こういった理由で、マインクラフト・サーバーがもっとも必要するのはTick毎に実行できるCPUインストラクションの数ということであり、その性能を上げる目的でオーバクロッキングが重要になってくる。
幸い、Piは「オーバクロッキング」を補償範囲内でサポートしている。(注意:いくつかの高度なオーバークロッキング設定は保証を無効にしてしまう。ただし raspi-config 画面からの変更はすべて補償範囲内。)
オーバークロックしてCPU処理速度を上げる
PiのCPU(汎用処理)、GPUコア(画像処理)、SDRAM(メモリー)のクロック周波数は工場出荷時に「安全な低めの値」に設定されている。
変更するには、やはり raspi-config から設定画面に行き、
項目7を選ぶ。
オーバークロックPresetを選ぶ画面が出てくる。
工場出荷時のプリセット(既定値)は「None」になっている。ARMのCPUは700MHz、GPU core は250MHz、SDRAMは400MHzで、最後にOvervoltという項目が0になっている。
(Overvoltについては脚注 *1に書いておきます。)
私の場合、まず「Medium」から始めて、段階的にオーバークロックを上げながらサーバーの挙動を確認した(っといっても大雑把な体感での判断で、きちんとベンチマークしたり温度を確認したわけではない。数千円のSoCコンピューターなのでその辺りはカジュアルに進めた。)
最終的には「Pi2」というPreset (Raspberry Pi 2 から新たに加わった)まで上げても、サーバーが特に異常な動作する様子もなかった。ただ、GPU coreのクロック周波数500MHzというのはちょっと高すぎなので、これは後でconfig.txtという設定ファイルを直接編集して微調整する予定。(config.txtを直接編集する場合は、保証を無効にするような設定をしてしまう可能性があるので注意が必要。)
次にメモリーの分配の最適化をする。
CPUとGPUのメモリーの分割
クロック周波数を上げる「オーバークロック」以外で、Piの最適化を図れるものに、「メモリースプリット」という設定項目がある。
PiではCPUとGPUが同じメモリを共有しており、GPUがまず定められた取り分を貰い、余った分が全てCPUにまわされる。なのでGPUへのメモリ配分を最小限にすることで、CPUが使えるメモリを増やすことができる。
おなじみの raspi-config 設定画面を開けて
項目8を選ぶ
アドバンス設定から、項目A3を選ぶ、
この設定画面ではGPU(グラフィック処理プロセッサー)が使用するメモリを変更できる。
Piをマインクラフト・サーバーとして使う上で、GPUのメモリは最小限でかまわないので、新しい値として16を設定する。
Piの最適化は以上。
ステップ5-Javaランタイムの最適化
マインクラフトはJava言語で書かれたJavaアプリケーションなので、通常のJavaアプリケーションと同様に、スタート時にいくつもの設定項目がある。
私の場合、以下のようなコマンドラインでサーバーをスタートしている。
以下にそれぞれのオプションの解説をする。
VMの種類
JavaのVMには clilent と server がある。詳細は省くが、server VM がマインクラフト・サーバーには適している。
ガーベッジ・コレクター(GC)メモリー
まず、マインクラフト・サーバーが必要とするGCメモリー。ネットでよく見るサイズは1GB。おそらくこれぐらいが大体の目安なんだと思う。このPiに搭載されているメモリーは1GB なので、当然きっちり1GBを渡すことは出来ないが、出来るだけ多く渡したい。
そこで、Pi起動後のフリーのメモリー量を調べてみると・・
ほぼ900MBほど余裕があることが分かった。
そこで、とりあえずJavaのメモリーを840で設定することにした(この設定は今後いろいろと様子をみながら変えることになると思う)。
Javaのオプションとして
と指定する。mxが最大で、msが最低限のサイズ。同じ値を指定すると、GCメモリーのサイズは固定される。
ガーベッジ・コレクターの種類
Javaにはいくつものガーベッジ・コレクターのアルゴリズムというか戦略が用意されている。GCの作業はアプリケーションの処理を完全に止めて行われるのでマインクラフト・サーバーの処理にも影響が出てくる。
OracleのJavaパフォーマンス・チューニングに関するドキュメントを読んだ感じでは
というオプションが適していると思われた。
以上がJavaランタイムの最適化。
クライエントからのプレイの制約
サーバーの設定は上記のような手順で完了したが、実は設定を一つ変えるごとにノートパソコンからクライエントを接続して一応の動作確認をしていた。
どの程度の負荷を与えたらサーバーがクラッシュするかもおおよその目安がついた。
まず、Survivalモードでこつこつと資源をあつめ、ゾンビから身を守る、といった遊び方ならかなり安定した状態で遊べる。これはCreativeモードと異なり、プレイヤーの移動そのものが自然に制約される(飛べない、というのが大きい)ので、更新されるワールドの範囲が比較的すくないから、だと思う。
一方、Creativeモードで遊ぶとなると、無限の資源(それはレッドストーン関連の動的な振る舞いをもつブロックも含む)、動物やモンスターの生成、そして空を縦横無尽に飛び回る、といった遊び方がメインになるので、それだけサーバーへの負荷が高くなる。
実際、ワールドの彼方めがけて飛ぶと、バニラの場合は多くの場合、「Tick処理が追いつかない」の警告メッセージのあと、ほどなくしてサーバーがクラッシュ、というのがよく起こった。Spigotの場合も起こったがその頻度はぐんと少なくなった印象がある。
私のざっくりとした感覚では、よほどのAbusive(酷い扱い)を意図的にしなければ、つまり常識的(?)な遊び方にとどまればRaspberry Pi 2をマインクラフト・サーバーのホストとして使うのは十分に可能だと思った。マインクラフト初心者がこじんまりと、ほのぼのと家を立てて、牛を育てて、麦を収穫する、という遊び方なら十分だと思う。
ただ、10歳の子供たちが「常識的」な遊び方をするか・・・というと、それは別の問題・・・ 例えば、溶岩で満たしたマスに、入れられるだけクリーパーを投入する、っといった遊び方をするので、そういうAbuseにはPiはとても耐えられないだろう、というのは私の予想。
*1:Overvolt について。調べたところ、こういうことらしい。
コンピューターは言うまでもなく0と1でデータや命令などを表す。1というのは実は電圧が0の状態の電圧に比べて2ボルト高い状態で表している。0から1に値が変わるとき、その変化は瞬間的ではなく、ある時間を要する。そこで、電源が非力な場合などは電圧の変化がクロックの周波数のペースに間に合わなくなって、1として解釈されるべきところが0として解釈されてしまう。仮にこれがアドレスのデータなら、メモリ上のとんでもない場所を指し示したりしてプロセスがクラッシュしたりする原因になってしまう。
さらに、この不安定な傾向は周波数を上げるオーバークロッキングではさらに顕著に現れることになる。
そこで、Overvolt機能が登場する。Overvoltの設定を例えば2にすると、それだけ電源供給を多め(??この辺りは電気工学が弱点の私は正しく説明できない・・・)にすることでより安定した0と1の状態を保つ、というのが原理。