我有一个程序在缓冲区中连接一些字符串。
之前我正在使用strncpy。在使用snprintf而不是strncat查看web上的一些建议后,我切换到了snprintf。但是,我注意到之前执行此部分程序(字符串连接)的延迟。这可能,snprintf可以减慢程序的执行速度吗?如果没有,那么我会在我的程序中寻找其他一些因素。
if(iOffset<MAX_BUFF_SIZE && iOffset>0)
{
.......
iOffset += snprintf(cBuff+iOffset, sizeof(cBuff)-iOffset, "%s", "String1");
......
}
我重复上面的代码片段12次,以便将字符串附加到cBuff。
编辑:每1秒后重复12次。
答案 0 :(得分:4)
有一些想法可以想到:
如果您不熟悉性能分析,或者非常渴望了解时间详细信息,则可以始终在代码周围包含计时器。请参阅gettimeofday()或clock()的参考资料以及有关这些代码的相应警告。基本上你可以在执行之前获得时间,之后的时间并比较它们。注释掉你的代码行并输入旧代码并计时。
尽管如此......这是探查器为您做的事情的一部分。找出“为什么”某些东西很慢的东西有时很复杂,因为可能还有其他考虑因素(即在硬件层面)你不知道。
与程序的总执行时间相比,执行12次函数可能是微不足道的。
答案 1 :(得分:4)
strncat
遇到Schlemiel the Painter问题。你使用snprintf
的方式不然(虽然也可以这样使用strncat
,并以这种方式回避问题。)
答案 2 :(得分:1)
假设您考虑到Chris Jester-Young提到的问题,通过考虑“Schlemiel the Painter”问题,您很可能会发现strncat()
的头对头比较比你snprintf()
更快 - 就像你使用它一样。
snprintf()
确实有(虽然很小,在这种情况下)必须解析strncat()
没有的格式字符串的开销。
您提供的代码段与the linked question中给出的示例不同,可能会更改比较。
斯蒂芬提到,对于大多数运行strncpy()
12次而非snprintf()
的平台,应该产生微不足道的差异。在这里使用分析器非常有用,可以确保您专注于正确的区域。
在您提供的示例中,您尝试将const字符串附加到缓冲区。如果您正在使用真实代码(而不仅仅是一个简单的示例),并且字符串复制确实是一个重要的执行时间区域,您可能能够优化该区域。
一种常见的优化方法是找到可以在编译时预先计算的计算,而不是在执行时。 如果您只对处理const字符串感兴趣,您可以有效地预先计算字符串的长度,然后使用memcpy()
而不是strncpy()
来执行字符串追加。 memcpy()
通常针对您的平台进行了优化。
当然,这样的解决方案将以牺牲缓冲区溢出和指针算法为代价。
答案 3 :(得分:1)
复制“重复连接”习惯并仅使用snprintf
来执行此操作并非真正遵循建议以避免strcat
。你应该做的事情如下:
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);
这比重复调用snprintf
快得多,这会给每次调用带来很多开销,实际上它会正确地使用这个习惯用法。
答案 4 :(得分:0)
我不是探查者,所以我不能肯定说什么是慢的。
正如@chris所提到的,strncat可以做多次工作而不是一遍又一遍地找到目标字符串的结尾。您可能已经能够缓解这种情况,因为它似乎正在跟踪消耗的空间,因此您可以在每次后续调用时从最后开始。
另一方面,与strcat或strcpy相比,snprintf可能需要做额外的工作,因为它必须在每次调用时解析“%s”以找出如何处理变量参数列表。
strncat运行得更快,我并不感到惊讶,特别是在缺乏激进的优化级别的情况下。
答案 5 :(得分:0)
那些提到在你注意到减速后不提早优化的人是愚蠢的。在这种情况下,您甚至不需要运行探查器。你已经有经验证据转向snprintf减慢了你的计划。
我在金融行业工作,业绩是关键,几乎总是喜欢sprintf到snprintf。可以在一个受控制的环境中编写快速稳定的应用程序。