0

次のプログラムは、ガベージ コレクションの負荷を示すカウンターを表示します。

一定期間、たとえば 1/60 秒のフレームごとに、たとえば MB 単位で負荷を確認できるようにしたいと考えています。

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace proj
{
    public class game : Microsoft.Xna.Framework.Game
    {
        private GraphicsDeviceManager graphics;
        private SpriteBatch sprite_batch;
        private SpriteFont font;

        public game()
        {
            graphics = new GraphicsDeviceManager(this);
        }

        protected override void Initialize()
        {
            Content.RootDirectory = "Content";
            sprite_batch = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("font");
            base.Initialize();
        }

        protected override void Update(
            GameTime game_time)
        {
            //base.Update(game_time);
        }

        protected override void Draw(
            GameTime gameTime)
        {
            GraphicsDevice.Clear(
                Color.DarkBlue);
            sprite_batch.Begin();
            sprite_batch.DrawString(
                font,
                ((float)GC.GetTotalMemory(true) / (1024 * 1024)).ToString(),
                //GC.GetTotalMemory(true).ToString(),
                new Vector2(20, 20),
                Color.White);
            sprite_batch.End();
            //base.Draw(gameTime);
        }
    }
}

ただし、このプログラムでは 0.4MB をわずかに超えているように見えますが、これは各フレームの舞台裏でいくつかの新しいオブジェクトが作成されることを期待していますが、それを超えると、((float)GC.GetTotalMemory(true) / (1024 * 1024)).ToString()作成中に Vector2 といくつかの数値と文字列の値しか表示されません。

コメントで発生するものをラップしたため、描画と更新中に同様にほとんど発生しない大規模なプログラムでは、多くのコードが存在し、そのうちのいくつかはプログラムの開始時に一度実行され、プログラムは一定の負荷を示します1 フレームあたり 90MB。

さらに、追加しようとしました:

pos n2;
for (UInt32 n = 0; n < 100000; n++)
{
    n2 = new pos(n, 0);
    func(n2);
}

どこ

public class pos
{
    public pos(
        float x,
        float y)
    {
        this.x = x;
        this.y = y;
    }

    public float
        x, y;
}

private void func(
    pos p)
{
}

描画しても、GC 値はほとんど変化しません。

私はこれを間違って解釈していますか?もしそうなら、どうすれば必要なものを表示できますか?

1 秒に 1 回程度実行が一時停止するという形で、GC がパフォーマンスの問題を引き起こしているようです。PC ではほとんど目立ちませんが、XBOX では非常に目立ちます。これが当てはまるかどうかを分析するためにこれを行っています。

たとえば、次のようなコードを (実行時のコードのパフォーマンスの観点から) 最適化できます。

loop()
{
    func(new pos(..., ...));
}

次のようなコードに:

pos p = new pos(0, 0);
loop()
{
    p.x = ...;
    p.y = ...;
    func(p);
}

疑わしい関連性がありますが、尋ねるかもしれません。GC に対する私のスタンスは、GC なしではオブジェクト指向プログラミング言語を選択して使用しないということです。良いコードを作成するために不可欠だと思います。


明確にするために。時間の経過に伴うガベージ コレクターの負荷を探しています。GC はこの情報をバイト形式で返すようですが、返される値はプログラム全体の合計メモリ使用量とより一致しているようです。


誰も実際に質問に答えていないことがわかります.1つの緊密な要求があり、質問は巨大になり、明らかな詳細で更新し続ける必要があります. ここでは、人々が要点を完全に見逃すのは簡単なようです。各フレームで何も起きていないときの 90MB のように、明らかに正しくない結果を表示しないアプリのアプリ内 GC ロード カウンターを使用できない理由がわかりません。

長い間使っていたので、今では実用的ではありません。

4

2 に答える 2

1

参加したばかりなのでコメントできませんが、あなたが望んでいるようです:

"I'm looking for the load on the garbage collector over time. Not the memory useage of the whole program. The GC seems to return this information in the form of bytes" 

もう存在している。システムに既にインストールされている標準の .net パフォーマンス カウンターを使用するだけです。[スタート] -> [コントロール パネル] -> [管理ツール] -> [パフォーマンス モニター] でアプリを起動し、パフォーマンス モニターを開き、アプリを選択して、.NET CLR メモリ カウンターの下に必要なものを追加します。本当に GC の問題があるかどうかを確認するのに役立つ優れたカウンターがあり、メモリの統計情報を提供し、さらに重要なことに、各世代のメモリの量、1 秒あたりのコレクション割り当ての頻度などを知ることができます。

お役に立てれば。

于 2012-05-06T01:53:42.377 に答える
0

まず、メモリを最適化したい場合は、メモリ プロファイラを使用する必要があります。必要なすべての詳細が表示されます (ボトルネックはどこにありますか? 私のコードが原因なのか、それともライブラリなのか?)。このようなヘルパーの構築は面倒で、エラーが発生しやすくなります。また、今の状態ではあまり教えてくれませんよね?

第 2 に、Vector2 は値型であるためnew Vector2(20, 20)、ガベージが発生することはありません (変数が閉じられていない、ボックス化されていない、イテレータ ブロックがないなど)。複数の文字列を描画する場合は、StringBuilder を取る DrawString を使用します。

private StringBuilder text = new StringBuilder();

    protected override void Update(GameTime game_time)
    {
        text.Remove(0, text.Length);
        text.Append((float)GC.GetTotalMemory(true) / (1024 * 1024)));
        //base.Update(game_time);
    }

もしそうなら、どうすれば必要なものを表示できますか?

質問が正しいかどうかはわかりませんが、時間の経過に伴うメモリ使用量を詳細に表示するには、特注のツールを使用してください。プロファイラーを取得します。

編集:

さらに、追加しようとしました:

pos n2;
for (UInt32 n = 0; n < 100000; n++)
{
    n2 = new pos(n, 0);
    func(n2);
}

ポスとは?Vector2のような値型ですか?Vector2 はガベージを発生させません (通常)。

1 秒に 1 回程度実行が一時停止するという形で、GC がパフォーマンスの問題を引き起こしているようです。PC ではほとんど目立ちませんが、XBOX では非常に目立ちます。これが当てはまるかどうかを分析するためにこれを行っています。

私はあなたの痛みを知っています。明らかな解決策は、割り当てを避けることです。避けられない場合は、単純なキャッシュ メカニズム (オブジェクトの HashSet/Dictionary) を構築し、それに応じて値を更新できます。ユーザーがゲームを開始する前に、できるだけロードします。

于 2012-05-06T00:35:51.657 に答える