例如,当打印像换行符这样的单个字符时,在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字节(常数比具有单个字符的字符串小得多(以字节为单位。。。(即
const char*
( - 字符和字符串的读取方式不同。。。在迭代字符串时直接访问字符,并对指向的的每个单独字符执行操作,结果存储回指针的地址中
- 字符串总是一个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天以上才能溢出…(。