2

応用

MMO に取り組んでいて、問題が発生しました。私が構築した MMO サーバーは高速で、UDP ソケットで最大 50 ミリ秒ごとにゲーム クライアントにメッセージをローカルに送信します。現在のメッセージ システムを介したサーバーからクライアントへのメッセージの例を次に示します。

count={2}body={[t={agt}id={42231}pos={[50.40142117456183,146.3123192153775]}rot={200.0},t={agt}id={4946}pos={[65.83051652925558, 495.25839757504866]}腐敗={187.0}}

count={2}, 2 = number of objects
[,] = array of objects

シンプルなテキスト パーサー、コードを作成しました: http://tinypaste.com/af3fb928

私は次のようなメッセージを使用します:

    int objects = int.Parse(UTL.Parser.DecodeMessage("count", message));
    string body = UTL.Parser.DecodeMessage("body", message);
    for (int i = 0; i < objects; i++)
    {
        string objectStr = UTL.Parser.DecodeMessage("[" + i + "]", body);
        // parse objecStr with UTL.Parser.DecodeMessage to extract pos & rot and apply to objects
    )

問題

オブジェクトが 60 以上になると、パフォーマンスが劇的に低下します。

質問

MMO やリアルタイム オンライン ゲームで、クライアントとサーバー間でメッセージをパッケージ化して読み取る標準的な方法は何ですか?

4

3 に答える 3

2

ここでは、バイナリ プロトコルの方がはるかに高速です。たとえば、渡す座標を取ります。それらをバイトとして転送すると、軸ごとに 8 バイトが必要になりますが、文字列表現では文字ごとに 2 バイトが使用されます (ASCII として転送しない限り、バイナリ double の方が小さくなります)。

次に、実際にその文字列を数値に変換するのは、より多くの作業です。最初に部分文字列を作成する必要があり、後でガベージ コレクションのオーバーヘッドが発生します。.NETdouble.Parseは非常に一般的であるため、数値を解析する必要がありますが、これは高速ではありません (ただし、公平を期すために、1 秒間に何十万もの double を解析できます)。さまざまな形式に対応する必要があります テキストに固執する場合は、独自の二重パーサーを作成することで顕著な速度が得られますが、前述のように、メッセージの解析がボトルネックである場合はバイナリを使用する必要があります。バイトを double に変換する (ちょっとしたunsafe魔法が必要です。サーバーを実行していて完全信頼モードが必要な場合は問題ありません) とは、8 バイトをコピーすることです。

あなたのメッセージが主に座標などである場合は、独自のバイナリ形式を作成することで多くのことを得ることができると思います.

于 2013-06-18T17:22:35.667 に答える
1

問題の1つは、不要な文字列のインスタンス化である可能性があります。連結、分割、またはサブストリングを取得するときはいつでも、スタック上に新しいストリングインスタンスを作成します。これは、元のストリングからコピーされ、後で収集する必要があります。

文字列を1文字ずつ繰り返すようにコードを変更し、元の文字列のみを使用してデータを解析してみてください。インデックス付けのみを使用する必要がindexOfあります。また、サブストリングの作成をまったく回避するために、ストリングオフセット+長さを受け入れる独自のintおよびfloatパーサーを作成することもできます。これがやり過ぎかどうかはわかりませんが、動作が遅いという確固たる証拠がある場合は、「時期尚早」の最適化ではありません。

また、プロトコルバッファを試しましたか?彼らのパフォーマンスはかなり良いはずだと思います(ベンチマーク用の小さなコンソールアプリを書くだけです)。または、JSONの場合、これは標準の簡潔な形式です(ただし、Json.NETがどのように最適化されているかについてはわかりません)。通常、パフォーマンスの点でハードコーディングされた特殊なパーサーに勝るものはありませんが、将来のメンテナンスを念頭に置いて、これらのプロトコルの1つを何よりも先に試します。

于 2012-01-15T00:00:40.137 に答える
1

Thriftのような RPC フレームワークを使用して、あなたに代わってリフティングを行うことを検討したいと思います。それはあなたのためにパッキングと解析を行い、バイナリでネットワーク経由で送信するので、より効率的です。

他にもたくさんのオプションがあります。いくつか比較してみます。

于 2012-01-14T23:55:27.770 に答える