我在另一个代码中看到了第二个,我想这个长度比较已经完成,以提高代码生产力。它在解析器中用于具有特定字典的脚本语言:单词长度为4到24个字母,平均为7-8个字母,字母表包括26个拉丁字母加上“@”,“$”和“_”。
长度比较用于转义==运算符使用STL字符串,这显然需要比简单整数比较更多的时间。但同时在给定字典中的第一个字母分布比字大小的分布宽,因此比较字符串的两个第一个字母通常通常不同于字符串的大小。这使得长度比较变得不必要。
我已经进行了一些测试,这就是我发现的:测试两个随机字符串比较百万次,第二种方式更快,所以长度比较似乎是有帮助的。但是在一个工作项目中,它在调试模式下运行速度更慢,在发布模式下运行速度更快。
所以,我的问题是:为什么长度比较可以加快比较,为什么它可以减缓它?
UPD:我也不喜欢第二种方式,但我认为这样做是有原因的,我想知道,这是什么原因。UPD2:说真的,问题不在于如何做到最好。在这种情况下,我甚至不再使用STL字符串了。毫无疑问,长度比较是不必要的和错误的等等。奇迹是 - 它确实在某个特定测试中稍微好一些。这怎么可能?
答案 0 :(得分:33)
如果重要,请假设您的图书馆已经这样做了。除非真的很重要,否则不要以这种方式搞砸你的代码进行微观优化。
答案 1 :(得分:12)
短路优化仅在以下情况下有所帮助:
数学上,让S为短路状态,F为满状态,P为短路情况的百分比(不需要完全状态)。
原始案件的平均成本(无短路)是F
短路优化的平均成本是S + F *(1-P)
因此,如果优化要有任何好处,则必须遵循以下规则:
S + F *(1-P)< ˚F
即
S< F * P
另外你写道:
显然需要比简单整数比较更多的时间。
这根本不明显。字符串比较在找到第一个差异时终止,因此根据您处理的字符串,它可能在绝大多数情况下终止于第一个或第二个字符。此外,只要两个字符串中有足够的数据,首先比较DWORDS(一次4个字符),即使对于较长的字符串,也可以优化比较。
随机测试数据和脚本解析之间的主要区别是真实数据远非随机。解析器很可能是确定性的,一旦匹配,就不再进行比较了。即使脚本数据也不是随机的 - 某些关键字可能比其他关键字使用得多。如果解析器以这样的方式构造,它首先检查最常用的关键字,那么令人惊讶的大量比较可能需要完成比较,因为当字符串匹配时总是需要完全比较。
答案 2 :(得分:5)
一般来说,你应该把它留给STL而不用担心它。
但是,如果这是一个你需要优化的区域(我非常怀疑),如果你理解字符串的字母分布/长度分布,你可以从字符串派生一个新类,并重载==运算符以最有效的方式为您的应用程序执行相等测试。 (长度优先,第一个角色优先,前进,后退,无论如何)。
这比在整个代码中散布“优化”要好。
答案 3 :(得分:4)
在随机测试中,字符串可能已经足够长以显示增益,而在实际情况下,您可以处理较短的字符串,并且两个比较的常数因子不会被不执行字符串比较部分的任何增益所抵消。测试。
答案 4 :(得分:4)
std :: string operator ==的实现无法知道首先检查长度或开始检查字符是否更快。清楚地检查长度是相同长度的弦的浪费。因此,STL的不同实现可能会以不同的方式执行。
仅将显式长度检查作为最终优化(明确注释),并且仅在您的探查器确认好处时才会进行。
答案 5 :(得分:1)
长度比较对我没有任何意义..使用比较运算符就足够了
答案 6 :(得分:0)
解雇您的STL实施。没关系
答案 7 :(得分:0)
长度比较是为了尝试一些短路优化。
我假设长度比较比完整的字符串比较更快,所以如果这可以消除99%的不匹配,那么它将比每次进行完整的字符串比较更快。
代码将执行长度比较,它将失败,然后它将忽略完整的字符串比较并跳过代码。
答案 8 :(得分:0)
std :: string的长度很可能是std :: string对象的成员。相比之下,第一个角色很可能在堆上。这意味着比较字符串长度可以改善引用的局部性。当然,通过短字符串优化,这变得更加复杂 - Lhs[0]
可能在堆上,而Rhs[0]
在堆栈上。