如何测试一个特定的C++语句比其他语句快还是慢



例如,当打印像换行符这样的单个字符时,在C++中使用cout时,以字符串或字符形式传递可能会更快?

cout << "n";

cout << 'n';

这个视频激励我写高效的代码。

你会如何测试这些东西?也许我可能想测试其他东西,看看哪个更快,所以知道如何自己测试这些东西会很有帮助。

理论上,如果去掉打印1000所用的时间,使用'n'而不是"n"会更快

记住: 单个字符可能不会比指针慢。。。因为指针指向每个字符的地址(就像容器一样(,这就是为什么它的字节大小不是固定的,并且字符只有一个地址,那就是它自己。。。仅1字节

// Works with C++17 and above...
#include <iostream>
#include <chrono>
template<typename T, typename Duration = std::chrono::milliseconds, typename ...Args>
constexpr static auto TimeElapsedOnOperation(T&& functor, Args&&... arguments)
{
auto const ms = std::chrono::steady_clock::now();
std::invoke(std::forward<decltype(functor)>(functor), 
std::forward<Args>(arguments)...);
return std::chrono::duration_cast<std::chrono::
milliseconds>(std::chrono::steady_clock::now() - ms);
}
int main()
{
std::cout << TimeElapsedOnOperation([]
{
for (auto i = 0; i < 1000; i++)
std::cout << "n";
}).count() << std::endl;
std::cin.get();
std::cout << TimeElapsedOnOperation([]
{
for (auto i = 0; i < 1000; i++)
std::cout << 'n';
}).count() << std::endl;
std::cin.get();
return 0;
}

它给出了以下输出:(可能发生不同的情况…(

<1000>换行符跟随

2195毫秒对于字符串"n"

更多<1000>换行符跟随

852毫秒对于字符'n'

2195-852=1343毫秒

它花费了1343(1.343秒(毫秒的时间。。。因此,我们可以近似地认为,它比仅使用'n'61.18%(1343/2195*100(

这只是一个近似值,因为在其他机器中的性能可能不同。。。

关于发生这种情况的原因:

  1. 单个字符(1字节(常数比具有单个字符的字符串小得多(以字节为单位。。。(const char*(
  2. 字符和字符串的读取方式不同。。。在迭代字符串时直接访问字符,并对指向的的每个单独字符执行操作,结果存储回指针的地址中
  3. 字符串总是一个char数组,而char被安全地认为是包含其各自数值的整数(扩展ASCII,从中分支出不同的字符编码(,1个字符的字符串是1个字符(及其地址…

所以也许(只是可能(你更倾向于使用'n'。。。

然而棘手";编译器可以随时优化您的代码从CCD_ 9到CCD_。。。,所以,实际上,我们永远猜不到,但仍然被认为是将char声明为char的良好做法。。。

仅理论考虑因素:

  • 一个字符可以直接打印出来,需要迭代一个字符串来找到终止的null字符
  • 可以传递单个字符并将其直接用作值;字符串是通过指针传递的,因此必须先解析地址,然后才能使用字符

所以至少,单个字符不能变慢。然而,一个足够聪明的编译器可能会发现常量一个字符串,并优化任何差异(尤其是如果运算符<<是内联的(。

如何测试:一开始,你会对一个尽可能少干扰测试的系统感兴趣(线程之间的上下文切换很昂贵(,所以最好关闭任何打开的应用程序。

一个非常简单的测试程序可能会经常重复使用这两个运算符,比如:

for(uint32_t loop = 0; loop < SomeLimit; ++loop)
{
// take timestamp in highest precision possible
for(uint32_t i = 0; i < Iterations; ++i)
{
// single character
}
// calculate difference to timestamp, add to sum for character
// take timestamp in highest precision possible
for(uint32_t i = 0; i < Iterations; ++i)
{
// string
}
// calculate difference to timestamp, add to sum for string
}

交错字符和字符串输出可能有助于在运行时获得更好的平均值。如果操作系统活动在测试期间发生变化,内部循环应该运行足够长的时间,以获得合理的测量时间间隔。

程序运行的时间越长,输出就越精确。为了防止溢出,请使用uint64_t收集总和(即使使用ns精度,程序也必须运行200000天以上才能溢出…(。

最新更新