关于C#:snprintf和strncat的执行速度如何比较?

How do the execution speeds of snprintf and strncat compare?

我有一个程序,可以在缓冲区中连接一些字符串。

我以前使用过strncpy。在研究了网络上的一些建议以使用snprintf代替strncat之后,我切换到了snprintf。但是,我注意到执行此部分程序(字符串串联)的延迟比之前要延迟。这有可能使snprintf减慢程序执行速度吗?如果没有,那么我会在程序中寻找其他因素。

1
2
3
4
5
6
if(iOffset<MAX_BUFF_SIZE && iOffset>0)
{
  .......
  iOffset += snprintf(cBuff+iOffset, sizeof(cBuff)-iOffset,"%s","String1");
  ......
}

为了将字符串附加到cBuff,我将上述代码段重复了12次。

编辑:每1秒重复12次。


strncat遭受画家Schlemiel的困扰。您使用snprintf的方式没有(尽管也可以使用strncat的方式,并以这种方式回避问题)。


我想到了一些建议:

  • 不要太早优化程序
  • 当您准备好进行优化时,请使用探查器之类的工具来发现真正的减速情况在哪里

如果您不熟悉概要分析,或者真的很想知道时序详细信息,则可以始终在代码周围包括计时器。请参阅有关gettimeofday()或clock()的参考以及有关这些代码的适当警告。本质上,您可以获取执行之前的时间,执行之后的时间并进行比较。注释掉您的代码行,并放入旧代码并计时。

话虽如此,这只是分析器为您执行的操作的一部分。找出缓慢的"为什么"有时是很复杂的,因为可能还有其他您没有意识到的注意事项(例如,在硬件级别)。

与程序的总执行时间相比,执行函数12次可能微不足道。


复制"重复级联"惯用语并仅使用snprintf来完成它并不是真正遵循避免strcat的建议。您应该执行以下操作:

1
snprintf(buf, sizeof buf,"%s%s%s%s", str1, str2, str3, str4);

这将比重复调用snprintf快得多,这将导致每次调用产生大量开销,并且实际上会正确使用该成语。


假设您考虑了Chris Jester-Young提到的问题,并考虑了"画家Schlemiel"问题,那么您可能会发现,在直接比较中,strncat()更快比snprintf()-以您使用它的方式。

snprintf()确实有(尽管是次要的)开销,必须解析strncat()不会的格式字符串。

您提供的代码段与链接问题中给出的示例足够不同,有可能更改比较。

正如史蒂芬(Stephen)所述,对于strncpy()相对于snprintf()运行12倍的大多数平台,其产生的差异可以忽略不计。在此处使用探查器将很有用,以确保您专注于正确的区域。

在您提供的示例中,您尝试将const字符串追加到缓冲区中。如果这是您在实际代码中所做的工作(而不只是一个简单的示例),并且字符串复制确实是执行时间的重要区域,则可以优化该区域。

一种常见的优化方法是找到可以在编译时而不是执行时预先计算的计算。如果只对处理const字符串感兴趣,则可以有效地预先计算字符串的长度,然后使用memcpy()而不是strncpy()来执行字符串追加。 memcpy()通常已针对您的平台进行了很好的优化。

当然,这种解决方案的代价是必须更多地注意缓冲区溢出和指针算术。


在您发现速度变慢后提早不进行优化的人很愚蠢。在这种情况下,您甚至不需要运行探查器。您已经有经验证据证明切换到snprintf会减慢您的程序的速度。

我在金融业工作,绩效是关键,并且几乎总是喜欢sprintf而不是snprintf。可以在一个受严格控制的环境中用它编写快速,稳定的应用程序。


我不是探查者,所以我不能肯定说什么很慢。

正如@chris所提到的那样,strncat可以一遍又一遍地查找目标字符串的末尾,从而完成了比所需更多的工作。您可能已经能够缓解这种情况,因为它似乎正在跟踪所消耗的空间,因此您可以从每个后续调用的结尾开始。

另一方面,与strcat或strcpy相比,snprintf可能需要做更多的工作,因为它必须在每次调用时都解析"%s "才能弄清楚如何处理变量参数列表。

对于strncat可以运行得更快,我并不感到惊讶,特别是在缺少积极的优化级别的情况下。