我是剖析新手。我想优化我的代码以满足时序约束。我使用Visual C ++ 08 Express,因此必须下载一个分析器,对我来说它非常困。我做了一些搜索,但发现没有关于Sleepy的体面教程,我的问题在这里: 如何正确使用?我掌握了分析的一般概念,所以我按照%排序来排序以找到我的瓶颈。首先,在此列表的顶部,我有 ZwWaitForSingleObject , RtlEnterCriticalSection , operator new , RtlLeaveCriticalSection , printf ,一些迭代器......在它们占用60%之后出现了我的第一个函数,第一个位置是Child Calls。有人可以解释一下为什么上面提到的,它们是什么意思,如果我无法访问这个关键的60%,我怎样才能优化我的代码? (对于“源文件”:未知......)。 另外,对于我的功能,我认为每条线都有时间,但事实并非如此,例如算术或某些函数没有时间(不嵌套在未使用的“if”子句中)。 最后一件事:如何发现某条线可以执行超高速,但被称为数千次,是实际的瓶颈?
最后,睡眠好吗?或者我平台的一些免费替代品?
非常感谢! 干杯!
我找到了另一个版本的探测器,名为plain Sleepy。它显示了一些片段被调用的次数加上行的数量(我猜它指向关键的片段)。所以在我的情况下.. KiFastSystemCallRet 需要 50%!这意味着它等待一些数据吗?如何改善这个问题,是否有一种可行的方法来跟踪导致这些多次调用的原因并最终删除/更改它?
答案 0 :(得分:5)
我想优化我的代码以满足时序约束
你正在经营这个行业的持续性问题。 你想找到方法让你的代码花费更少的时间,而你(和许多人)假设(并且已经被教导),唯一的方法就是采取各种各样的测量。
有少数观点,唯一需要推荐的是actual significant results(plus an ironclad theory behind it)。
如果你有一个“瓶颈”(并且你做了,可能是几个),它需要一些时间,比如30%。
只是将其视为可以找到的错误。
使用暂停按钮随机停止程序,仔细查看程序正在执行的操作以及执行操作的原因。 询问是否可以摆脱它。 这样做10次。平均而言,您会看到3个暂停的问题。 如果不是真的有必要,你不止一次看到的任何活动都是速度错误。 这并不能准确地告诉您问题的成本,但它确实能够准确地告诉您问题是什么,并且值得修复。 你可以通过这种方式看到没有分析器可以找到的东西,因为分析器 只是程序,不能对构成机会的内容持宽容态度。
有些人厌恶风险,认为可能无法提供足够的加速值。 当然,收益率很低的可能性很小,但这就像投资一样。 该理论平均说它是值得的,并且也有很小的机会获得高回报。 无论如何,如果你担心风险,可以再多做一些样品来解决你的担忧。
解决问题之后,剩下的每个瓶颈都会占用更大的百分比,因为它们并没有变小,但总体程序确实如此。 因此,当您重复整个过程时,它们将更容易找到。
有很多关于剖析的文献,但实际上说它在实践中实现了多少加速。 Here's a concrete example加速了近3个数量级。
答案 1 :(得分:2)
我使用GlowCode(商业产品,类似于Sleepy)来分析本机C ++代码。您运行检测过程,然后执行程序,然后查看该工具生成的数据。仪表步骤在每个方法的入口点和出口点注入一点跟踪功能,并简单地测量每个功能运行完成所需的时间。
使用调用图分析工具,我列出了从“最常用时间”到“最少使用时间”的方法,该工具还显示了呼叫计数。只需钻进最高百分比的例程,就可以看出哪些方法使用的时间最多。我可以看到一些方法非常慢,但钻进它们我发现它们正在等待用户输入或服务响应。有些人花了很长时间,因为他们每次调用时都会调用几次内部例程。我们发现有人犯了编码错误,并且为列表中的每个项目重复走一个大的链表,当他们真的只需要走一次时。
如果按“最常调用”排序为“最少调用”,则可以看到从任何地方调用的一些微小函数(迭代器方法,如next()
等)。要检查的内容是确保最常调用的函数非常干净。在一个名为500次的例程中保存一毫秒以绘制一个屏幕将使该屏幕加速半秒。这有助于您确定哪些是最重要的工作场所。
我见过两种使用分析的常用方法。一种是进行一些“通用”分析,运行一系列“正常”操作,并发现哪些方法最大程度地降低了应用程序的速度。另一种是进行特定的分析,重点关注特定用户对性能的抱怨,并通过这些功能来揭示他们的问题。
我要提醒您的一件事是将您的更改限制为会对用户体验或系统吞吐量产生重大影响的更改。将鼠标点击一毫秒的剃须对平均用户没有影响,因为人类的反应时间并不那么快。赛车手的反应时间在8毫秒范围内,一些优秀的抽搐游戏玩家甚至更快,但像银行出纳员这样的普通用户的反应时间将在20-30毫秒范围内。好处可以忽略不计。
进行20个1毫秒的改进或者一个20毫秒的改进将使系统响应更快。如果你能够通过许多小改进做出一次重大改进,那就更便宜,更好。
同样,每秒处理100个用户的服务削减一毫秒将使性能提高10%,这意味着您可以改进服务以处理每秒110个用户。
值得关注的是,严格地编码更改以提高性能通常会增加复杂性,从而对代码的结构产生负面影响。假设您决定通过缓存结果来改进对数据库的调用。你怎么知道缓存何时失效?你是否添加了缓存清理机制?考虑一个金融交易,其中循环所有订单项以产生运行总计很慢,因此您决定保持runningTotal累加器更快地回答。您现在必须修改runningTotal以适应各种情况,如线条空白,反转,删除,修改,数量更改等。这会使代码更复杂,更容易出错。