C++ C++;哪个功能更快?重复分配或重复创造
我认为下面的图片可以很好地解释这一点,但区别主要在于每次调用都会分配一个静态变量,或者每次调用都会创建一个普通变量(?) 谢谢你的见解 编辑:我添加了一个快速程序。我不知道这有多无意义,但它们同时执行。我觉得这不是一个好的测试。我想这不值得担心C++ C++;哪个功能更快?重复分配或重复创造,c++,performance,function,variables,static,C++,Performance,Function,Variables,Static,我认为下面的图片可以很好地解释这一点,但区别主要在于每次调用都会分配一个静态变量,或者每次调用都会创建一个普通变量(?) 谢谢你的见解 编辑:我添加了一个快速程序。我不知道这有多无意义,但它们同时执行。我觉得这不是一个好的测试。我想这不值得担心 #include <iostream> #include <time.h> using namespace std; #define ONE_BILLION 1000000000 #define HUNDRED_MILLIO
#include <iostream>
#include <time.h>
using namespace std;
#define ONE_BILLION 1000000000
#define HUNDRED_MILLION 100000000
long long functionStatic(int arg)
{
static long long randNum;
srand(time(NULL));
randNum = rand() % 20;
return arg + randNum;
}
long long functionLocal(int arg)
{
long long randNum;
srand(time(NULL));
randNum = rand() % 20;
return arg + randNum;
}
int main()
{
long long timeStart;
long long duration;
long long randNum;
long long accum = 0;
timeStart = clock();
for (int i = 0; i < HUNDRED_MILLION; i++)
{
srand(time(NULL));
randNum = rand() % 50;
accum += functionStatic(randNum);
}
cout << "Time for static variable function: " << clock() - timeStart << " milliseconds" << endl << endl;
timeStart = clock();
for (int i = 0; i < HUNDRED_MILLION; i++)
{
srand(time(NULL));
randNum = rand() % 50;
accum += functionLocal(randNum);
}
cout << "Time for local variable function: " << clock() - timeStart << " milliseconds" << endl;
return 0;
}
#包括
#包括
使用名称空间std;
#定义十亿亿欧元
#定义亿欧元100000000
长函数静态(int arg)
{
静态长随机数;
srand(时间(空));
randNum=rand()%20;
返回arg+randNum;
}
长函数本地(int arg)
{
朗朗纳姆;
srand(时间(空));
randNum=rand()%20;
返回arg+randNum;
}
int main()
{
长时间启动;
持续时间长;
朗朗纳姆;
长累计=0;
timeStart=clock();
对于(int i=0;i<1亿;i++)
{
srand(时间(空));
randNum=rand()%50;
accum+=函数静态(随机数);
}
cout对于使用-O2构建的g++4.9.2,使用静态会有轻微的损失,因为它不会优化存储
// static int a;
// a = 2;
// a += Someclass::number + Someclass::number2;
mov 0x0(%rip),%eax # Get Someclass::number
add 0x0(%rip),%eax # Add Someclass::number2
add $0x2,%eax # Add 2
mov %eax,0x0(%rip) # Store result in a
retq # return
a
不是静态的版本少了一条指令:
// int a = 2;
// a += Someclass::number + Someclass::number2;
mov 0x0(%rip),%eax # Get Someclass::number
add 0x0(%rip),%eax # Add Someclass::number2
add $0x2,%eax # Add 2
retq # Return
但是,对于clang 3.6.0,结果是相同的:
// static int a;
// a = 2;
// a += Someclass::number + Someclass::number2;
mov 0x0(%rip),%eax
mov 0x0(%rip),%ecx
lea 0x2(%rax,%rcx,1),%eax
retq
// int a = 2;
// a += Someclass::number + Someclass::number2;
mov 0x0(%rip),%eax
mov 0x0(%rip),%ecx
lea 0x2(%rax,%rcx,1),%eax
retq
让我们看看这两种情况都发生了什么
情况1:-int a
作为局部变量
在这种情况下,编译器可以进行优化,也就是说,它可以将其放入寄存器或缓存中。因此,如果函数被多次调用,显然,这一函数将比静态
变量稍有优势
案例2:-使其成为static int a
在这种情况下,一旦变量初始化,它将被分配到程序的静态数据区,并一直保存到程序退出。
编译器也拒绝对此函数执行任何优化,因此每次调用函数时,都会从主存中提取一个
,然后进行修改,然后再次写入主存,这将转化为比第一种情况下的汇编指令数量更多
最终结论:-第一种情况可能比第二种情况好。但情况可能并非总是这样,因为有更多的因素会影响性能,如其他人提到的编译器、CPU、底层硬件平台或操作系统。除了“视情况而定”之外,没有真正的答案 您的问题实际上属于“过早优化”的范畴。您没有提到“测试”或“分析”之类的概念,而是单独担心特定代码构造的性能,这一事实支持这种特性 使用静态方法a(一次性)在第一次调用函数之前的某个时间创建该静态,并每次重新分配。在运行时,这意味着访问和/或修改内存中该位置的最新值。这可能意味着,根据调用函数的频率和CPU的工作方式,访问处理器缓存,返回RAM(比缓存慢),或从交换空间检索该位置的数据(如果在硬盘驱动器上交换空间,则比内存慢得多)。因此,性能取决于主机系统的内存体系结构,并且可能会有一些变化 使用自动变量通常意味着分配和初始化堆栈空间的某个区域。该区域的性能同样取决于主机系统的内存体系结构,但不太可能像静态变量那样可变 编译器还可以完全优化自动变量的使用,将其放入机器寄存器或其他技巧以提高代码的性能。当涉及静态变量时,编译器进行此类优化的空间较小 然而,最终,差异可能是微不足道的——即使在频繁调用的代码中也是如此。频繁调用的函数中的其他东西——算法等——可能对性能的影响比担心变量应该是静态的还是自动的更大
我建议首先为可读性和可维护性对函数进行编码。这意味着,在实践中,可能不会使变量成为静态的-因为这意味着有更多定义的路径供数据进出函数,因此更难理解。然后在实际用例中测试代码的性能。如果发现了某些性能问题,请通过探查器运行它,并找出真正的瓶颈(如果有的话)在哪里。更有可能的是,代码中的变量
a
甚至不会与任何瓶颈有关。或者,如果是,则是低阶效应-其他因素将占主导地位。因为在现实世界中,driv影响程序性能的因素通常是代码不同部分之间的交互,而不是一个变量属性的微小调整所影响的因素。有一点尚未真正涉及,我认为这与您的问题有关。在您的示例中,您碰巧使用了int。因为您使用了int(适用于任何普通类型),静态初始化可以以特别有效的方式完成。但是,在函数中创建静态变量可能会非常昂贵:
struct A {
A(double y) : z(y) { }
double z;
};
A func(double x) {
static A a(0);
a.z += x;
return a;
}
编译为(使用-O2):
发生了什么事?像a这样的静态局部变量必须在第一次调用func时初始化一次。但是如何确保这一点呢?必须创建一个不可见的布尔变量,将其初始化为false,在初始化之前检查它,只有ini
func(double): # @func(double)
push rax
mov al, byte ptr [rip + guard variable for func(double)::a]
test al, al
jne .LBB0_3
mov edi, guard variable for func(double)::a
movsd qword ptr [rsp], xmm0 # 8-byte Spill
call __cxa_guard_acquire
movsd xmm0, qword ptr [rsp] # 8-byte Reload
test eax, eax
je .LBB0_3
mov qword ptr [rip + func(double)::a], 0
mov edi, guard variable for func(double)::a
call __cxa_guard_release
movsd xmm0, qword ptr [rsp] # 8-byte Reload
.LBB0_3:
addsd xmm0, qword ptr [rip + func(double)::a]
movsd qword ptr [rip + func(double)::a], xmm0
pop rax
ret