2012-03-24 10 views
7

私は、Linuxベースのサーバを使ったマルチプレイヤーオンラインゲームを開発しているプログラマーです。我々は、私たちの世界に「インスタンシエート」アーキテクチャを採用しています。これは、世界のエリアに入る各プレイヤーが、そのエリアのコピーを党員と共にプレイすることを意味し、同じエリアでプレイしている他のすべてのプレーヤーとは独立しています。fork()とコピーライト時のメモリ共有の効率化

内部的には、インスタンスごとに個別のプロセスを使用します。最初に、各インスタンスプロセスが起動し、指定された領域に必要なリソースだけをロードし、ランダムな地形を生成して、プレイヤーから新しい接続を許可します。インスタンスによって使用されるメモリの量は、リソースおよびエンティティを含むランダムに生成されたレベルを含めて、通常約25メガでした。

インスタンスのメモリ使用量を減らし、起動時間を短縮するために、インスタンスが必要とするすべてのリソースをロードする単一のマスターインスタンスを作成するアプローチに変更しました(約150メガ新しいインスタンスが必要な場合は、fork()関数を使用して新しいインスタンスを生成し、コピーオンライトメモリ共有を使用して、新しいインスタンスには "一意の"データセットのメモリのみが必要です。ランダムに生成されたレベルのフットプリントと、各インスタンスの一意のデータを構成するエンティティは、約3〜4メガのメモリです。

残念ながら、メモリ共有はうまくいっていないと思います。多くのメモリページが共有されていないように見えます。

最初に、プリフォークインスタンスに多くのデータセットをロードすると、フォークされた各インスタンスに必要なメモリがダウンしますが、最終的にプリフォーク内の資産を多くロードすると、それぞれのフォークされたインスタンス。

私たちが持っていた最良の結果は、約80メガのデータセットをプリフォークして読み込み、残りの部分を読み込むように新鮮なインスタンスを要求することでした。この結果、1インスタンスあたり約7-10の追加メガワイトと80メガの固定コストが発生します。確かに良い改善ですが、理論的には最高です。

150メガのデータセット全体を読み込んでフォークすると、フォークされた各インスタンスは約50メガバイトのメモリを使用します。単に何もしないよりもかなり悪いです。

私の質問は、すべてのデータセットをプリフォークインスタンスにロードし、各インスタンスのメモリフットプリントとしてインスタンスデータごとに最小限のセットしか得られないようにする方法です。


は、私はここで何が起こっているかのよう理論を持っていると、誰かがこれが事実であることを私のために確認を支援することができるだろうかと思いまして。

mallocフリーチェーンと関係があると思います。プリフォークインスタンスの各メモリページには、おそらくメモリのいくつかのフリースポットが残っています。ランダムなレベルの生成中に、ページ内の空き領域の1つに収まるようなものが割り当てられた場合、そのページ全体がフォークされたプロセスにコピーされます。

代替ヒープを作成し、プロセスで使用されるデフォルトヒープを変更することができます。これが可能であれば、問題が取り除かれます。 Linuxでこのようなことをする方法はありますか?私の調査はあなたができないことを示しているようです。

既存のmallocフリーチェーンを何らかの形で破棄して、mallocに後続の呼び出しのためにオペレーティングシステムから新しいメモリを割り当てることができれば、別の解決策があります。私はmallocの実装を見て、これが簡単に可能かどうかを調べようとしましたが、やや複雑なように思えました。誰もがこの分野に関するアイデアやこのアプローチをどこから始めるべきかの提案があれば、それを聞いてみたいです。

最後に、ここで間違っている可能性のあることについて誰か他のアイデアがある場合は、実際に聞いてみたいと思います。どうもありがとう!

答えて

2

代替ヒープを作成し、プロセスによって使用されるデフォルトのヒープ を変更することができます。これが可能であれば、 問題が削除されます。 Linuxでこのようなことをする方法はありますか?

I Unixでは、簡単にmmap(2)メモリバイパスmallocとすることができます。

私はまた、「頼りになる牛」の全体を捨てるだろう。私はマスタープロセスmmapいくつかのメモリ(80M、150M何でも)を持って、それに物を書いて、mprotect(2)経由で読み取り専用をマークし、そこからそれを取る。これは本当の問題を解決し、コードを変更する必要はありません。

+0

これは大規模な既存のコードベースであり、私たちのリソースローダーはすべてそれらをうまく利用するため、malloc/newを完全にバイパスすることはできません。私はアプローチを排除するつもりはないが、私は可能な限り誰かelsesメモリアロケータを使い続けたいと思います。 – Negs

+1

@Negsカスタムアロケータを使うことも、 'malloc'をハイジャックすることもできます。しかし、第2段落を読んでください。牛に頼るのを止めて、あなた自身の 'mmap'をしてください。 – cnicutar

+0

それでも、私はカスタムアロケータを書く必要があります。私はこれに頼ることができますが、私はそれをする必要がないソリューションを探したいと思います。おそらく私のニーズを容易にするために既存のmallocの周りにラッパーのアプローチのいくつかの? – Negs

関連する問題