こんにちは、マッドフォースンデです。
マビノギのゲームサーバーに関するお話、その第1回目!
今回はシングルスレッドとマルチスレッドについて説明します。
まず、説明と理解を助けるために適切な例を挙げてみましょう!
私たちはスタートアップ企業に勤めていて、昨日新しいプログラムの開発依頼が来ました。
注文が入ったら、お客さんに腸詰めを1つずつ配るというプログラムなのですが、
プログラム名を「腸詰め」とし、お客さんに腸詰めを配るのにかかる時間は1秒に設定しました。
この時、「腸詰め」プログラムを使って10人のお客さんに10個の腸詰めを配るのにかかる時間はどのくらいでしょうか。
答えが分かりますか?
この問題の答えは「腸詰め」がマルチスレッド基盤で開発されたかどうかによって答えが複数ある可能性があります。
区分 | シングルスレッド | マルチスレッド(10スレッド) |
スレッド数 | 1 | 10 |
所要時間 | 10 | 1.xx |
はい、そうです。所要時間から推測できるようにシングルスレッドとマルチスレッドの最大の違いは、
マルチスレッドは並列処理が可能な点です。
では、現在のマビノギゲームサーバーはシングルスレッドでしょうか?それともマルチスレッドでしょうか?
ご推察の通り、現在のマビノギのゲームサーバーはシングルスレッド基盤で作られています。
サードパーティモジュールとクライアントのパケットの入出力を担当する部分は、マルチスレッド基盤で作られていますが
実際のクライアントのリクエストを処理するゲームロジックスレッドはシングルスレッド基盤で作られています。
そのため、自分のクライアントがリクエストしたパケットをサーバーで処理するためには先に
リクエストされたすべてのパケットが処理されるまで待つ必要があります。
したがって、クライアントのリクエストが一斉に集中すると、サーバーでボトルネックが発生します。
そのため、よく知られているラグ現象を経験することになります。
エタニティプロジェクトを進めながら、上記の問題について多くの議論を重ねました。
結論としては、ゲームロジックスレッドをマルチスレッドに変更する作業を進めることにしました。
そうすればボトルネックを最小限に抑えることができると判断したからです。
上の表で、「腸詰め」をマルチスレッドで開発した時の所要時間がなぜ1秒ではなく 1.xx秒なのでしょうか?
数学的に計算してみると、スレッドの数がN個になるとプロセスのパフォーマンスもN倍になるはずですが
実際はそうではありません。ハードウェア、ソフトウェア的な限界が存在するからです。
ハードウェアの限界はCPUの性能を意味するので別途説明せず、ソフトウェア的な限界だけを説明します。
マルチスレッド環境ではスレッド間でメモリ領域を共有する「臨界領域」にアクセスする時、待ち時間が発生します。
そのため、1秒ではなく1.xx秒になるのです。
待ち時間が発生する理由は次の通りです。
再び「腸詰め」を例に挙げると、「腸詰め」の臨界領域は「腸詰め10個が盛られた皿」です。
複数のスレッドが皿から同時に腸詰めを取ろうとすると腸詰めが破れたり、腸詰めが3個残っていると思っていたら
2個しか残っていなかったりなどの「同期エラー」が発生する場合があります。
そのため、これを防ぐためにプログラマーが直接「同期エラー」防止コードを作成する必要があります。
このコードは最初にアクセスしたスレッドの処理が終わるまで他のスレッドを待機させる役割をするので
待ち時間が発生します。
マビノギコンテンツのフィールドレイドを例に「臨界領域」の説明を加えます。
モクルカルフィが様々なスキル攻撃を受けています。
この時、モクルカルフィの生命力の数値が「臨界領域」で処理されなければなりません。
シングルスレッドでは順次スキルが処理されるので別途追加処理は必要ありませんでしたが、
マルチスレッドでは複数のスレッドでモクルカルフィの生命力の数値を減少させる状況が発生するので
追加処理が必要です。
例のようにマビノギのゲームサーバーのコードには「臨界領域」が無数に存在しています。
マルチスレッド環境に切り替えるということは、このすべての「臨界領域」に「同期エラー」が発生しないように
コードを全面的に修正しなければならないので多くの努力と時間が必要な作業です。
しかし、ミレシアンの方に今よりもっと快適なエリン環境を提供するのが私たち開発チームの使命ですので
最善を尽くして頑張ります。
これからも応援のほどよろしくお願いします。
長文でしたが、最後まで読んでいただきましてありがとうございました。
『Writer マッドフォースンデ』