大小写不敏感的字符串比较的性能差异化

3
所以,我的博士项目依赖于我已经构建了近3年的一款软件。它可以运行,很稳定(不会崩溃或抛出异常),我正在使用发布版本。但我意识到有一个巨大的性能问题,因为我过度依赖boost::iequals。我知道,在SO上有很多关于这个的内容,这不是一个关于如何做的问题,而是为什么会发生这种情况。考虑以下内容:
#include <string.h>
#include <string>
#include <boost/algorithm/string.hpp>

void posix_str ( )
{
    std::string s1 = "Alexander";
    std::string s2 = "Pericles";
    std::cout << "POSIX strcasecmp: " << strcasecmp( s1.c_str(), s2.c_str() ) << std::endl;
}

void boost_str ( )
{
    std::string s1 = "Alexander";
    std::string s2 = "Pericles";
    std::cout << "boost::iequals: " << boost::iequals( s1, s2 ) << std::endl;
}

int main ( )
{
    posix_str();
    boost_str();
    return 0;
}

我使用了valgrind和cachegrind测试了这段代码,令我惊讶的是,boost的速度比本地posix或std方法慢了4倍(std方法似乎使用了相同的posix)。即使考虑到C++提供的安全保障,四倍速度差距也很大。为什么会出现这种情况?我希望其他人能运行这段代码并解释是什么导致了性能损失。是所有分配造成的吗?(从调用映射中看来确实如此)我不是在批评boost,我喜欢并且无处不用它。编辑:这张图表阐述了我的意思

请发布演示您问题的测试代码。这些代码不能帮助我们理解您对原始代码所做的更改,而且仅凭您的话,我不会相信它们,除非看到展示问题的代码。因此,请展示代码以及您如何测量它。 - Nawaz
1
@Nawaz 没有问题。测试代码已经显示,boost::iequals 比 strcasecmp 慢了4倍,我正在尝试理解原因。 - Ælex
1
它在哪里显示比正常慢四倍?你能展示一下证明的代码吗? - NathanOliver
@NathanOliver 添加了来自 kcachegrind 的输出图表。 - Ælex
1
你只运行了一次来得到这些结果吗?你使用了任何优化吗?理想情况下,你需要运行这些函数几千次以获得良好的执行速度平均值。 - NathanOliver
@NathanOliver 我在 for 循环中运行了 100 次。我可以更长时间地运行它,但我认为下面 sbabbi 的答案解释了为什么会发生这种情况。 - Ælex
1个回答

7
Boost::iequals是具有区域设置感知能力的。从其定义(在此)中可以看到,它接受一个可选的第三个参数,默认为默认构造的std::locale,表示由std::locale::global设置的当前全局C++区域设置。
这更或多或少意味着编译器无法事先知道将使用哪个区域设置,这意味着对于每个字符在当前区域设置下转换为小写字母都会调用某个函数进行间接调用。
另一方面,strcasecmp文档指出:
在POSIX区域设置中,strcasecmp()和strncasecmp()的行为就像字符串已经被转换为小写字母,然后执行了字节比较。在其他区域设置中,结果是未指定的。
这意味着区域设置是固定的,因此您可以期望它已被大量优化。

谢谢sbabbi,那非常有意义! - Ælex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接