wp7 xna 中的随机性能崩溃?
我正在使用 xna 开发我的第一款 Windows Phone 7 游戏。 经过一些测试后,我注意到游戏动画出现了短暂的减速,并进行了一些性能测试,但无法完全消除减速。 现在我创建了一个空项目,其中只有一个 DrawableGameComponent 继承类绘制有关 runningslow 标志、绘制/更新时间(传递给方法)以及垃圾收集器是否正在运行的文本。 奇怪的是,即使使用这种简约的代码,延迟似乎也大约每 1 到 5 秒发生一次。我指的是绘图花费的时间而不是 33 毫秒 > 50 毫秒的延迟。有时甚至在这个简约的项目中设置了运行慢标志。 从我的实验来看,垃圾收集器似乎不是造成这种情况的主要原因,因为他执行的次数要少得多。 手持机也设置为飞行模式,因此无法通信。
更新代码:
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);
}
我还注意到它并不总是发生。
I'm working on my first game for Windows Phone 7 with xna.
After some testing I noticed short slow downs in the game animations and implemented some performance tests but wasn't able to remove the slow downs completely.
Now I have created an empty project in which only a DrawableGameComponent inherited class draws text about the runsslow flag, the Draw/Update time (gets passed to the methods) and if the garbage collector was running.
Strange is that even with this minimalistic code the delays seem to occure around once every 1 to 5 second. With a delay I'm refering to when a drawing takes instead of 33 millisconds >50 milliseconds. Sometimes even the runsslow flag is set in this minimalistic project.
From my experiments the garbage collector seems to be not the main reason for this as he executes far less.
The handy is also set to flight mode so no communication.
The update code:
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;
}
}
The draw code:
//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);
}
What I have noticed also is that it doesn't occure all the time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这可能会有所帮助( 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 来查看是否存在内存压力?
This might help ( http://www.gavpugh.com/2010/04/01/xnac-avoiding-garbage-when-working-with-stringbuilder/ )
even using StringBuilder the garbage collector can still be at fault.
The link above explains that some of the Append calls definetly generate garbage. It also has a class that helps to generate less garbage with stringBuilder Appends.
In addition ( http://devblog.andyc.org/2011/05/garbage-control/ ) uses a no garbage wrapper on string builder.
Have you tried using CLR Profiler to see if there is memory pressure building?