miyuriの日記: ネタ選びが上手いのか 5
サーバーマシン1台で同時接続者数1万名を実現するにはどうすればいいのかというノウハウと考え方
読み難い日本語訳なのは置いといて、nerdウケが良さそうな感じ。
たくさんのキャラクターとたくさんのプレイヤーがものすごい動きを見せる、そういうテストプログラムを作ったんです。
中略
WindowsのネットワークのOverlapped I/Oを呼び出すこの関数のところで最も時間がかかっていた、ということが分かったのです。
興味深い。
で、対策方法がコレ。
リモートオブジェクトをロックできない場合は、それは諦めて、他のリモートオブジェクトのロックを試みます。そして、他の用事をその間に見ればいいんです。さっきロックできなかったオブジェクトはまた改めてロックすればいいんです。こうなりますと、スレッドが待機時間にならず、つまりコンテキストスイッチングが発生しませんので、多数のオブジェクトを順次処理できます。
多数のクライアントに同じメッセージを送信する場合、つまりマルチキャストで使うことができます。ProudNetは5ミリ秒以下時間ごとにパケットをまとめて送るんですけれども、これをコアレッセンスと言います。ネーグルアルゴリズムと同じようなものなんですが、これをマニュアルで制御するんです。これをするのはシリーウィンドウシンドロームをなくすためなんです。またこれには良い、面白い効果も現れまして、先ほど非同期送信関数がありましたが、このコールの回数が減りますので、サーバの性能も少し良くなります。
リモートオブジェクトっていうモノに送信データを突っ込むのかな。
シリーウィンドウシンドロームがどうこうって事は、マルチキャストではないよね。
設計を変えずに力技でパフォーマンスを改善しましたっていう感じに見えるなー。
ほとんどが既知の一般則なような... (スコア:1)
なんか方言多くてわかりにくいけど。
# 方言って言えば今の職場も方言多いな...。
Re:ほとんどが既知の一般則なような... (スコア:2)
ロックを取れなかったら他の事をするっていうのは誰でも思いつくけど、どれくらい有効なんだろう。
やたらと粒度を細かくしているみたいだから、保留するオーバヘッドの方が大きくなりそうなものだけど。
Re:ほとんどが既知の一般則なような... (スコア:1)
例えば接続先がA,B,CとあったらマルチスレッドもマルチタスクもしないでA,B,Cと試すってだけの話なんじゃないかな?
で、全部試してダメなら初めてコンテキストスイッチを伴う待ちに入ってみたりとか。
でもそれなら接続先をいくつかまとめて一つのプロセスに任せるという分散でかなり簡単に並列化できるはずだから、もしかしたら違うかも。
処理グループをいくつかまとめてプロセスに投げ込んで分散するとなると「プロセス数<=プロセッサ数」に拘る必要ないしなー。
やっぱり本人が気付いてない粒度設計ミスかな?
ちょっと読み切れないや。
しかし...「コンテキストスイッチ」ってのは本当は「(メモリ空間切り替えという意味での)プロセススイッチ」の事を指してるんじゃなかろうか。ただのコンテキストスイッチだったらレジスタとスタックの保存と復帰だけだからそんなに重くはないし...もしかすると最初は接続先一つにプロセス一つ割り当ててたんじゃなかろうか。これ自体は一般的だけどね。
そりゃまぁ、応答時間性能稼ぐより総負荷が軽いことが大事ならスレッドレベルであってもコンテキストスイッチしない方がいいけど、それをフレームワークレベルでやるのが「ファイバー」って奴だし、「ロック確保の順番が同じなのが大事」ってやたら言ってるけど15年くらい前に読んだ本に載ってた話だし、どのみちあんまり目新しいことは言ってないぽい。
ん? (スコア:0)
単純にOSの制限でマルチスレッド等ができない(しないほうが良い)部分はシングルスレッドにしてQueue的に利用しただけなんじゃないですか?
#非常にわかりやすい内容だと思いましたよ
Re:ん? (スコア:2)
技術的な内容は全部分かるけど、プログラムの全体像やデータの扱いは全く分からないよね。
ああ、こういうのはnerdウケが良さそうってね。
自前で時間を意識してパケットを繋げる処理を入れるっていうのは、送信データを作ってからWinSockに渡すまでの間の設計を間違えてる気がするんだよ。