4

我是分析的新手。我想优化我的代码以满足时序约束。我使用 Visual C++ 08 Express,因此不得不下载一个分析器,对我来说它非常困。我做了一些搜索,但没有找到像样的关于 Sleepy 的教程,我的问题是:如何正确使用它?我掌握了 profiling 的大体思路,所以我按照 %exclusive 进行排序,找到我的瓶颈。首先,在这个列表的顶部,我有ZwWaitForSingleObjectRtlEnterCriticalSectionoperator newRtlLeaveCriticalSectionprintf,一些迭代器......在他们占据了大约 60% 之后,我的第一个函数出现了,第一个位置是子调用。有人可以解释一下为什么上面提到的出现,它们是什么意思,如果我无法访问这个关键的 60%,我该如何优化我的代码?(对于“源文件”:未知...)。另外,对于我的函数,我认为我每行都有时间,但事实并非如此,例如算术或某些函数没有时间(未嵌套在未使用的“if”子句中)。最后一件事:如何找出某些行可以超快执行,但被调用数千次,成为实际的瓶颈?

最后,瞌睡好吗?或者我的平台的一些免费替代品?

帮助非常感谢!干杯!

        • 更新 - - - - -

我找到了另一个版本的分析器,称为plain Sleepy。它显示了一些片段被调用了多少次加上行数(我猜它指向关键的一个)。所以在我的情况下.. KiFastSystemCallRet需要50%!这意味着它正在等待一些数据,对吗?如何改善这件事,是否有一种体面的方法来追踪导致这些多次调用的原因并最终删除/更改它?

4

2 回答 2

5

我想优化我的代码以满足时序约束

你在这个行业遇到了一个持久的问题。您想找到使您的代码花费更少时间的方法,而您(和许多人)假设(并且已经被教导)唯一的方法是进行各种测量。

有少数观点,它唯一要推荐的是实际的显着结果加上它背后的铁定理论)。

如果你有一个“瓶颈”(你有,可能有几个),它只需要一小部分时间,比如 30%。
只需将其视为待发现的错误

使用暂停按钮随机停止程序,并仔细查看程序在做什么以及为什么这样做。询问是否可以摆脱它。这样做 10 次。平均而言,您会在 3 次停顿中看到问题。您多次看到的任何活动(如果不是真正必要的)都是速度错误。这并不能准确地告诉您问题的成本是多少,但它确实可以准确地告诉您问题是什么,并且值得解决。您会以这种分析器无法找到的方式看待事物,因为分析器只是程序,不能对机会的构成有广泛的认识。

有些人厌恶风险,认为它可能无法提供足够的加速而不值得。诚然,低回报的可能性很小,但这就像投资。该理论表明,平均而言,这是值得的,而且获得高回报的可能性也很小。无论如何,如果您担心风险,再多做几个样品就可以解决您的担忧。

解决问题后,剩余的瓶颈每个都占较大的百分比,因为它们并没有变小,但整个程序却变小了。因此,当您重复整个过程时,它们会更容易找到。

有很多关于分析的文献,但实际上很少能说明它在实践中实现了多少加速。 这是一个具有近 3 个数量级加速的具体示例。

于 2012-11-30T15:05:48.757 回答
2

我使用 GlowCode(商业产品,类似于 Sleepy)来分析本机 C++ 代码。您运行检测过程,然后执行您的程序,然后查看该工具生成的数据。检测步骤在每个方法的入口点和出口点注入一点跟踪函数,并简单地测量每个函数运行到完成所需的时间。

使用调用图分析工具,我列出了从“最常用”到“最少使用时间”排序的方法,该工具还显示调用计数。只需深入研究百分比最高的例程,就可以向我展示哪些方法使用时间最长。我可以看到有些方法非常慢,但深入研究它们后我发现它们正在等待用户输入或服务响应。有些需要很长时间,因为他们每次调用都会调用一些内部例程数千次。我们发现有人犯了一个编码错误,并且正在为列表中的每个项目重复遍历一个大型链表,而他们实际上只需要遍历一次。

If you sort by "most frequently called" to "least called", you can see some of the tiny functions that get called from everywhere (iterator methods like next(), etc.) Something to check for is to make sure the functions that are called the most often are really clean. Saving a millisecond in a routine called 500 times to paint a screen will speed that screen up by half a second. This helps you decide which are the most important places to spend your efforts.

我已经看到了两种使用分析的常用方法。一种是做一些“一般”的分析,运行一套“正常”的操作,并发现哪些方法最能减慢应用程序的速度。另一种是做具体的分析,关注具体的用户对性能的抱怨,并通过这些功能来揭示他们的问题。

我要提醒您的一件事是将您的更改限制在那些会显着影响用户体验或系统吞吐量的更改。将鼠标点击缩短一毫秒对普通用户来说并没有什么不同,因为人类的反应时间并没有那么快。赛车手的反应时间在 8 毫秒范围内,一些精英 twitch 游戏玩家甚至更快,但银行柜员等普通用户的反应时间在 20-30 毫秒范围内。好处将是微不足道的。

进行 20 个 1 毫秒的改进或 2 个 20 毫秒的更改将使系统响应更快。如果你能在许多小改进上做一个大改进,那就更便宜更好了。

同样,将每秒处理 100 个用户的服务缩短 1 毫秒将带来 10% 的改进,这意味着您可以改进服务以每秒处理 110 个用户。

令人担忧的原因是,为了提高性能而进行的严格编码更改通常会通过增加复杂性而对代码的结构产生负面影响。假设您决定通过缓存结果来改进对数据库的调用。你怎么知道缓存什么时候失效?是否添加缓存清理机制?考虑一个金融交易,其中循环遍历所有行项目以产生运行总计很慢,因此您决定保留 runningTotal 累加器以更快地回答。您现在必须针对各种情况修改 runningTotal,例如行空、反转、删除、修改、数量变化等。它使代码更复杂,更容易出错。

于 2012-11-30T16:06:13.167 回答