2

我正在使用 xna 为 Windows Phone 7 开发我的第一款游戏。经过一些测试后,我注意到游戏动画出现了短暂的减速并进行了一些性能测试,但无法完全消除减速。现在我创建了一个空项目,其中只有一个 DrawableGameComponent 继承类绘制有关 runsslow 标志、Draw/Update 时间(传递给方法)以及垃圾收集器是否正在运行的文本。奇怪的是,即使使用这个极简代码,延迟似乎大约每 1 到 5 秒发生一次。延迟我指的是何时绘制而不是 33 毫秒 > 50 毫秒。有时甚至在这个简约项目中设置了 runsslow 标志。从我的实验来看,垃圾收集器似乎不是造成这种情况的主要原因,因为他执行的次数要少得多。

更新代码:

    public override void Update(GameTime gameTime)
    {
        elapsedTime += gameTime.ElapsedGameTime;
        timeSpanUpdate.Add(gameTime.ElapsedGameTime.TotalMilliseconds);

        if (elapsedTime.TotalMilliseconds >= timeToElapseForVisualisation)
        {
            //update the values messured
            elapsedTime -= TimeSpan.FromMilliseconds(timeToElapseForVisualisation);
            //get the values we are interested in
            double sum = 0;
            maxUpdateTime = int.MinValue;
            foreach (double val in timeSpanUpdate)
            {
                sum += val;
                maxUpdateTime = (int)Math.Max(maxUpdateTime, val);
            }
            averageUpdateTime = (int)(sum / timeSpanUpdate.Count);
            timeSpanUpdate.Clear();

            sum = 0;
            maxDrawTime = int.MinValue;
            foreach (double val in timeSpanDraw)
            {
                sum += val;
                maxDrawTime = (int)Math.Max(maxDrawTime, val);
            }
            averageDrawTime = (int)(sum / timeSpanDraw.Count);
            timeSpanDraw.Clear();
        }

        if (gameTime.IsRunningSlowly)
        {
            runsSlow = true;
            timeToShowRunsslowRemaining = timeToShow;
        }
        else if (timeToShowRunsslowRemaining > 0)
        {
            timeToShowRunsslowRemaining -= gameTime.ElapsedGameTime.TotalMilliseconds;
        }
        else
        {
            runsSlow = false;
        }
    }

抽奖代码:

    //we use stringbuilders as strings passed to drawstring can induce the gc
    private StringBuilder drawText = new StringBuilder("Draw max: ");
    private StringBuilder updateText = new StringBuilder("Update max: ");
    private StringBuilder runsslowYes = new StringBuilder("runsslow: yes");
    private StringBuilder runsslowNo = new StringBuilder("runsslow: no");

    public override void  Draw(GameTime gameTime)
    {
        DateTime now = DateTime.Now;
        timeSpanDraw.Add((now - lastDrawCall).TotalMilliseconds);
        lastDrawCall = now;

        drawText.Remove("Draw max: ".Length, drawText.Length - "Draw max: ".Length);
        drawText.Append(maxDrawTime);
        updateText.Remove("Update max: ".Length, updateText.Length - "Update max: ".Length);
        updateText.Append(maxUpdateTime);

        spriteBatch.Begin();
        if (maxDrawTime >= thresholdMaxDelays)
        {
            spriteBatch.DrawString(spriteFont, drawText, drawTextPos, Color.Red);
        }
        else
        {
            spriteBatch.DrawString(spriteFont, drawText, drawTextPos, Color.White);
        }

        if (maxUpdateTime >= thresholdMaxDelays)
        {
            spriteBatch.DrawString(spriteFont, updateText, updateTextPos, Color.Red);
        }
        else
        {
            spriteBatch.DrawString(spriteFont, updateText, updateTextPos, Color.White);
        }

        if (runsSlow)
        {
            spriteBatch.DrawString(spriteFont, runsslowYes, runsslowTextPos, Color.Red);
        }
        else
        {
            spriteBatch.DrawString(spriteFont, runsslowNo, runsslowTextPos, Color.White);
        }


        spriteBatch.End();

        base.Draw(gameTime);
    }

我还注意到它并非一直都在发生。

4

1 回答 1

2

这可能会有所帮助(http://www.gavpugh.com/2010/04/01/xnac-avoiding-garbage-when-working-with-stringbuilder/)即使使用 StringBuilder 垃圾收集器仍然可能出错。上面的链接解释了一些 Append 调用肯定会产生垃圾。它还有一个类可以帮助使用 stringBuilder Appends 生成更少的垃圾。

此外(http://devblog.andyc.org/2011/05/garbage-control/)在字符串生成器上使用无垃圾包装器。

您是否尝试过使用 CLR Profiler 来查看是否存在内存压力?

于 2011-06-09T19:40:13.150 回答