【发布时间】:2012-06-24 17:19:46
【问题描述】:
[ [ EDIT 2x ] 我认为我原来的问题措辞错误,所以我把它放在下面,并准确地重写了我想要得到的内容,以供未来的读者阅读。 ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~
[新的、闪亮的、清晰的问题,措辞更好]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我有一个正在为模拟/游戏框架运行的循环。这个循环中有几个地方需要确定已经过去了多少时间 - 实际上 - 已经过去了,以便这些特殊地方的逻辑 - 特别是渲染和更新 - 可以正常工作。它可以选择固定时间步长(unfixed[update/render] 为假)。
当基于断点的调试在应用程序的任何点进行时,就会出现问题,因为它使用秒表来计算已经过去了多少实时(为了物理和动画以真实的速度移动,而不是基于关于计算机可以生成多少帧)。
它看起来(大致)像这样,对应用程序循环的每个“部分”使用多个秒表,需要知道自该“部分”上次发生以来已经过去了多少时间:
while ( RunningTheSimulation ) {
/* ... Events and other fun awesome stuff */
TimeSpan updatedifference = new TimeSpan( updatestopwatch.ElapsedTicks );
if ( unfixedupdate || updatedifference > updateinterval ) {
Time = new GameTime( updatedifference,
new TimeSpan( gamestopwatch.ElapsedTicks ) );
Update( Time );
++updatecount;
updatestopwatch.Reset( );
updatestopwatch.Start( );
}
TimeSpan renderdifference = new TimeSpan( renderstopwatch.ElapsedTicks );
if ( unfixedrender || renderdifference > renderinterval ) {
Time = new GameTime( renderdifference,
new TimeSpan( gamestopwatch.ElapsedTicks ) );
Render( Time );
++rendercount;
renderstopwatch.Reset( );
renderstopwatch.Start( );
}
}
关于变量的一些信息:
updatestopwatch 是 Stopwatch 用于在 Update() 函数之外花费的时间,
renderstopwatch 是一个 Stopwatch,表示在 Render() 函数之外花费的时间,并且
gamestopwatch 是一个Stopwatch,表示模拟/游戏本身的总经过时间。
当我在应用程序的任何地方进行调试时,就会出现问题。因为秒表是实时测量的,所以任何类型的基于断点的调试都将完全取消模拟,因为无论我是否在调试应用程序,秒表都会继续计算时间。我没有使用秒表来衡量性能:我使用它们来跟踪更新、渲染和其他事件(如上图所示)再次发生之间的时间。当我断点并分析并修复 Update() 中的错误时,这会变得非常令人沮丧,但是 Render() 时间完全关闭,以至于任何显示的模拟结果都会被报复性地踢到脸上。
也就是说,当我完全停止调试时,这显然不是问题,但是我有很多开发工作要做,而且我要调试很长时间,所以只是假装这不是不方便就赢了不工作,不幸的是。 =[
我查看了性能计数器,但我似乎无法理解如何让它们在我正在尝试做的事情的上下文中工作:渲染和更新可以包含任意数量的任意代码(它们'特定于在此while 循环之上运行的任何模拟),这意味着我无法稳定地为循环的各个组件执行PerformanceCounter.Increment()。
我将继续探讨 System.Diagnostics 和其他 .NET 命名空间,但到目前为止,我对如何“忽略”在附加的调试器中花费的时间一无所知...
有人有什么想法或见解吗?
[ [ EDITS 5x ] 更正了拼写错误并确保所有内容的格式正确。对于那个很抱歉。 ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[原始的,不太清楚的问题]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我在 C# 应用程序中运行了一个恒定循环,我一直在调试它。我目前正在使用秒表,但我可以使用任何其他机制来跟踪经过的时间。当我在这个循环中的某处使用断点之类的事情时,我的问题就开始了(包含在典型的while (true) { ... }中:
if ( unfixedupdate || updatedifference > updateinterval )
{
Time = new GameTime( updatedifference,
new TimeSpan( gamestopwatch.ElapsedTicks ) );
Update( Time );
++updatecount;
updatestopwatch.Reset( );
updatestopwatch.Start( );
}
时间测量本身很好,但它测量实际实时 - 包括我花在调试上的任何时间。这意味着如果我在updatestopwatch.Reset() 之后闲逛 17 秒,这会在我的循环中复杂化,并且 - 对于该循环的至少 1 次重新运行 - 我必须处理我在实时考虑到所有我的计算。
有什么方法可以连接到调试器以了解它何时冻结应用程序,以便我可以反测量时间并相应地减去它?正如所标记的那样,我为此使用 .NET 和 C#,但与 Visual Studio 相关的任何内容都可能有助于我朝着正确的方向前进。
[编辑]
为了提供更多信息,我使用了几个秒表(用于更新、渲染和其他一些事件,它们都在不同的消息队列中)。如果我在 Update() 或应用程序的任何其他部分设置断点,秒表将准确测量它们之间花费的实时时间。这包括我花在调试应用程序的各种完全不相关的组件上的时间,这些组件被称为Update() 或Render() 或Input() 等的下游。显然模拟的时间(由传递到顶层更新、渲染等的 GameTime 参数控制) .functions) 将无法正常工作,即使 CPU 只用了 13 毫秒来完成更新功能,我也花费了 13 秒的额外调试时间(查看变量然后继续模拟);问题是我会看到其他秒表突然占了 13 额外 秒的时间。如果还是不明白,我再补充。
【问题讨论】:
-
您能描述一下您希望如何处理这些性能数据吗?调试器开销可能会以更微妙的方式干扰性能测量,而不是简单地将 UI 等待时间添加到 Stopwatch 实例。如果您尝试优化此循环,最好不要在进行测量时使用调试器。
-
你不能在 Update() 之后但在 updatestopwatch.Reset() 调用之前设置断点吗?
-
我拥有的不仅仅是更新循环;有一个渲染循环以及其他被捕获和使用的事件。因此,将断点放在其他地方并不是真正的解决方案。
标签: c# .net breakpoints visual-studio-debugging