跟踪调试器中花费的时间

时间:2012-06-22 11:55:01

标签: c# .net breakpoints visual-studio-debugging

[[编辑2x]我认为我已经把我原来的问题措辞错了,所以我已经把它放到了下面并重写了我想要的内容,以供将来的读者使用。 ]

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~
[更好的措辞新的,有光泽的,明确的问题]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我有一个运行模拟/游戏框架的循环。这个循环有几个地方需要确定实际上已经过了多少时间,这样这些特殊地方的逻辑 - 特别是渲染和更新 - 才能正常工作。它可以选择是固定时间步(unfixed[update/render]是假的)。

当基于断点的调试在应用程序的任何一点完成时出现问题,因为它使用秒表来计算实时已经过了多少(为了物理和动画以实际速度移动,而不是基于计算机可以生成多少帧。)

看起来(大致)这样,使用 多个秒表为每个'部分'应用程序循环需要知道自那个' part'部分已经过了多长时间上次发生

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( );

    }
}   

有关变量的一些信息:

对于在Update()函数之外花费的时间,

updatestopwatchStopwatch

对于在Render()函数之外花费的时间,

renderstopwatchStopwatch,并且

gamestopwatch对于模拟/游戏本身的总耗用时间是Stopwatch

当我在应用程序中的任何地方进行调试时,会出现问题。因为秒表是实时测量的,所以任何基于断点的调试都会完全抛弃模拟,因为秒表将保持计时,无论我是否调试应用程序。我没有使用秒表测量性能:我使用它们来跟踪重新发生更新,渲染和其他事件之间的时间,如上所示。当我在Update()中断点并分析并修复错误时,这会非常令人沮丧,但是Render()时间完全关闭,以至于任何模拟结果的显示都会被虚假地踢到脸上。

那就是说,当我完全停止调试时,它显然不是问题,但是我有很多开发工作要做,而且我要调试很长时间,所以只是假装不幸的是,这并不是一件不方便的工作。 = [

我查看了Performance Counters,但我似乎无法理解如何让他们在我尝试做的事情中工作:渲染和更新可以包含任何数量的任意代码(它们特定于在此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秒,这会加到我的循环上 - 至少重新运行该循环 - 我必须处理我实时花费的额外时间考虑到我的所有计算。

有没有什么方法可以挂钩调试器知道什么时候冻结应用程序,所以我可以反时间并相应地减去它?标记为,我使用.NET和C#,但与Visual Studio相关的任何内容都可能有助于我朝着正确的方向前进。

[编辑] 为了提供更多信息,我使用了几个秒表(用于更新,渲染和一些其他事件都在不同的消息队列中)。如果我在Update()或应用程序的任何其他部分中设置断点,则秒表将准确测量它们之间的实时时间。这包括我花时间调试应用程序中各种完全不相关的组件的时间,这些组件称为Update()Render()Input()的下游等。显然模拟的时间(由GameTime控制)参数传递到顶层更新,渲染等功能)如果,即使CPU只花了13毫秒来完成更新功能,我也会花费 13秒额外调试(看变量然后继续模拟);问题是我会看到其他秒表突然占据<13>额外秒的时间。如果它仍然没有意义,我会再次进入。

3 个答案:

答案 0 :(得分:2)

改用性能计数器。进程CPU时间应该是一个很好的指示器(但不如实时秒表准确),不应该干扰调试。

答案 1 :(得分:0)

可能的解决方案是使用Debug.WriteLine()将您的本地(或您尝试调试的任何数据)写入输出。

答案 2 :(得分:0)

您未能解释您实际尝试调试的内容,以及为什么动画计时器完全按照预期的时间运行是一个问题。知道当您休息时,时间会继续。实际问题是什么?

此外,请记住,在启用优化的情况下在发行版中运行时,调试时的计时不会接近测量的任何时间。如果您想测量帧到帧的时间,请使用商业配置文件工具。查找方法或函数所花费的时间恰好是它们的目的。

如果您想调试动画是否正常工作,请使用依赖项注入和时间提供程序接口创建一个确定性测试,在该测试中您提供时间,而不是取决于挂钟。

本文有一个很好的例子: https://www.toptal.com/qa/how-to-write-testable-code-and-why-it-matters