delphi – 为什么CharInSet比Case语句更快?
我很困惑在CodeRage今天,Marco Cantu说CharInSet很慢,我应该尝试一个Case语句。我在我的解析器中这样做,然后用AQTime检查加速是什么。我发现Case语句要慢得多。
4,894,539处决:
时间为0.25秒。 但同样数量的处决:
对于“while True”为.16秒,第一种情况为.80秒,else为0.13秒,总共为1.09秒或超过4倍。 CharInSet语句的汇编代码是:
而案例逻辑就是这样的:
case逻辑看起来我使用非常高效的汇编器,而CharInSet语句实际上必须调用CharInSet函数,它在SysUtils中也很简单,它是:
我认为这样做的唯一原因是因为Delphi 2009中不再允许[”,#10,#13,#0]中的P ^,所以调用类型的转换是允许的。 无论如何,我非常惊讶,仍然不信任我的结果。 AQTime测量出错了,我在这个比较中缺少一些东西,还是CharInSet真正有价值的功能呢? 结论: 我想你得到了,巴里。感谢您抽出时间并做详细的例子。我在我的机器上测试了你的代码,并获得了.171,.066和.052秒(我猜我的桌面比你的笔记本电脑要快一些)。 在AQTime中测试代码,它给出了三个测试的0.79,1.57和1.46秒。在那里,您可以看到仪器的大量开销。但真正令我惊奇的是,这种开销将显而易见的“最佳”结果改变为CharInSet函数,这实际上是最差的。 所以Marcu是正确的,而CharInSet更慢。但是,在Set方法中,通过使用AnsiChar(P ^)提取CharInSet正在做的事情,无意中(或者也可能是故意的)给了我更好的方法。除了比例方法的次要速度优势之外,它也比使用案例更少的代码和更容易理解。 您也让我意识到使用AQTime(和其他仪器分析器)不正确优化的可能性。知道这将有助于我的决定Profiler and Memory Analysis Tools for Delphi,它也是我的问题How Does AQTime Do It?的另一个答案。当然,AQTime不会更改代码,当它的工具,所以它必须使用一些其他的魔法来做到这一点。 所以答案是AQTime显示导致错误结论的结果。 跟进:我把这个问题留给了AQTime的结果可能是误导的“指责”。但是,为了公平起见,我应该引导你仔细阅读这个问题:Is There A Fast GetToken Routine For Delphi?开始考虑AQTime给出了误导的结果,并得出结论。 解决方法
AQTime是一个仪器分析器。仪表分析器通常不适合测量代码时间,特别是在像您这样的微型基准测试中,因为仪器的成本往往超过被测量的成本。另一方面,仪器仪表仪表能够分析内存和其他资源的使用情况。
定期检查CPU位置的采样分析器通常更适合测量代码时间。 在任何情况下,这是另一个microbenchmark,它确实表明一个case语句比CharInSet快。但是,请注意,set检查仍然可以与typecast一起使用以消除截断警告(实际上这是CharInSet存在的唯一原因): {$apptype console} uses Windows,SysUtils; const SampleString = 'foo bar baz blah de;blah de blah.'; procedure P1; var cp: PChar; begin cp := PChar(SampleString); while not CharInSet(cp^,[#0,';','.']) do Inc(cp); end; procedure P2; var cp: PChar; begin cp := PChar(SampleString); while True do case cp^ of '.',#0,';': Break; else Inc(cp); end; end; procedure P3; var cp: PChar; begin cp := PChar(SampleString); while not (AnsiChar(cp^) in [#0,'.']) do Inc(cp); end; procedure Time(const Title: string; Proc: TProc); var i: Integer; start,finish,freq: Int64; begin QueryPerformanceCounter(start); for i := 1 to 1000000 do Proc; QueryPerformanceCounter(finish); QueryPerformanceFrequency(freq); Writeln(Format('%20s: %.3f seconds',[Title,(finish - start) / freq])); end; begin Time('CharInSet',P1); Time('case stmt',P2); Time('set test',P3); end. 它在我笔记本电脑上的输出是: CharInSet: 0.261 seconds case stmt: 0.077 seconds set test: 0.060 seconds (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |