修剪函数的性能表现

7

我旧的修剪函数:

string TailTrimString (const string & sSource, const char *chars) {
  size_t End = sSource.find_last_not_of(chars);
  if (End == string::npos) {
    // only "*chars"
    return "";
  }
  if (End == sSource.size() - 1) {
    // noting to trim
    return sSource;
  }
  return sSource.substr(0, End + 1);
}

我决定使用boost,而不是它,并编写了以下简单代码:

string TailTrimString (const string & sSource, const char *chars) {
    return boost::algorithm::trim_right_copy_if(sSource,boost::algorithm::is_any_of(chars));
}

我很惊讶地发现新功能的运行速度要慢得多。我进行了一些分析,发现函数is_any_of非常慢。可能boost的实现比我的相当直接的实现更慢吗?有没有什么东西可以代替is_any_of以提高性能?我在boost的邮件列表中也发现了这个问题的讨论,但我仍然不确定如何改进代码的性能。我使用的boost版本是1.38,这是相当旧的版本,但我猜这段代码从那时起并没有太大变化。谢谢。

你为什么要重新实现一个已经工作的函数? - John Dibling
1
我重新实现它只是因为我期望boost能够提供更好的性能。但我仍然不明白,为什么boost的性能会更差。 - Igor
@Igor:你有对代码进行分析并确定TailTrimString是需要修复的问题吗? - John Dibling
@Igor,也许你可以采用稍微不同的方法,目前你的修剪函数是非破坏性的,它能否变成破坏性的?即从源中擦除,以便保存自己的副本?或者可能参考目标并调用assign(而不是substr)-如果仍然是瓶颈,您可以尝试使用C函数进行重写... - Nim
确保您正在测试优化的代码。在我的测试中,第二个版本比第一个版本慢约30%,但是如果没有进行优化,则第二个版本需要花费300-400%的时间。第二个版本仍然较慢,但(也许?)不像您想象的那么慢。 - Nate
显示剩余6条评论
3个回答

4

使用Boost的实现比我的相当直接的实现慢,这可能吗?

当然可能。

有什么东西可以替代is_any_of以提高性能吗?

有的——就是您最初的代码。您没有提到它存在缺陷,或者重新使用Boost实现的原因。如果原始代码没有缺陷,则没有有效的理由放弃原始实现。

将Boost引入代码库是有意义的。它带来了许多有用的功能。但是为了使用新技术而摧毁一个函数是一个很大的新手错误。

编辑:

针对您的评论:

我仍然不明白,为什么Boost的性能更差。

手工制作的函数旨在为一个特定的应用程序执行一个特定的任务,通常比通用解决方案更快。Boost是一个伟大的通用工具库,可以节省大量编程和缺陷。但它是通用的。您可能只需要以特定方式修剪字符串,但Boost处理一切。这需要时间。


1
关于相对性能的问题,std::string::find_last_not_of将包装C字符串例程(例如strcspan),这些例程非常快,但是boost::algorithm::is_any_of使用(可能已经使用过,在后来的版本中可能已经改变!)一个std::set用于要查找的字符集,并在此集合中检查每个字符-这将远远不如快速!
编辑:只是为了回应,您的函数有效,它没有出现故障,也不慢,所以不要费心去更改它...

1
关于相对性能的问题,回答如下:
您正在使用 boost::algorithm::trim_right_copy_if,根据名称,它会在修剪之前创建输入的副本。尝试使用 boost::algorithm::trim_right_if,看看是否有更好的性能。该函数将在原地执行操作,而不是在新字符串上执行。

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