C++ 这是一个生动的证明,你不是在测量构造函数,而是在测量其他东西
当您启用C++ 这是一个生动的证明,你不是在测量构造函数,而是在测量其他东西,c++,performance,constructor,compiler-optimization,default-constructor,C++,Performance,Constructor,Compiler Optimization,Default Constructor,当您启用-O1优化时,for循环使用T退化为1: 测试ebx,ebx jle.L3 mov-eax,0 .L4: 添加eax,1 cmp-ebx,eax jne.L4 .L3: 对于Foo和Bar。也就是说,转化为一个平凡的for(inti=0;i
-O1
优化时,for
循环使用T代码>退化为1:
测试ebx,ebx
jle.L3
mov-eax,0
.L4:
添加eax,1
cmp-ebx,eax
jne.L4
.L3:
对于Foo
和Bar
。也就是说,转化为一个平凡的for(inti=0;i循环
当您启用-O2
或-O3
时,它会得到完全优化
没有优化(-O0
),您将获得以下程序集:
mov DWORD PTR [rbp-4], 0
.L35:
mov eax, DWORD PTR [rbp-4]
cmp eax, DWORD PTR [rbp-68]
jge .L34
lea rax, [rbp-64]
mov rdi, rax
call Foo<int>::Foo()
lea rax, [rbp-64]
mov rdi, rax
call Foo<int>::~Foo()
add DWORD PTR [rbp-4], 1
jmp .L35
.L34:
及
Bar::Bar()
推动rbp
mov rbp,rsp
副区长,16
mov QWORD PTR[rbp-8],rdi
mov rax,QWORD PTR[rbp-8]
莫夫尔迪,拉克斯
调用std::vector::vector()
不
离开
ret
正如你所看到的,它们也是一样的
1 GCC 8.3我怀疑你认为你看到的速度差异主要是时间安排不当的副产品,这是不真实的
为了查看生成的结果,我稍微简化了代码,只留下以下内容:
#include <vector>
template <typename T>
struct Foo
{
std::vector<T> data_;
Foo() = default;
};
template <typename T>
struct Bar
{
std::vector<T> data_;
Bar() {};
};
int main() {
Foo<int> f;
Bar<int> b;
}
#包括
模板
结构Foo
{
std::矢量数据;
Foo()=默认值;
};
模板
结构条
{
std::矢量数据;
Bar(){};
};
int main(){
福福;
b栏;
}
然后我把它放在这里,以便于查看生成的代码
gcc 9.2似乎为两个CTOR生成了相同的代码,在这两种情况下都是这样:
push rbp
mov rbp, rsp
sub rsp, 16
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
call std::vector<int, std::allocator<int> >::vector() [complete object constructor]
nop
leave
ret
push-rbp
mov rbp,rsp
副区长,16
mov QWORD PTR[rbp-8],rdi
mov rax,QWORD PTR[rbp-8]
莫夫尔迪,拉克斯
调用std::vector::vector()[完整对象构造函数]
不
离开
ret
Clang生成的代码略有不同,但(同样)这两个类的代码相同:
push rbp
mov rbp, rsp
sub rsp, 16
mov qword ptr [rbp - 8], rdi
mov rdi, qword ptr [rbp - 8]
call std::vector<int, std::allocator<int> >::vector() [base object constructor]
add rsp, 16
pop rbp
ret
push-rbp
mov rbp,rsp
副区长,16
mov qword ptr[rbp-8],rdi
mov rdi,qword ptr[rbp-8]
调用std::vector::vector()[基本对象构造函数]
加上rsp,16
流行限制性商业惯例
ret
Intel icc几乎相同,为这两个类生成以下代码:
push rbp #8.5
mov rbp, rsp #8.5
sub rsp, 16 #8.5
mov QWORD PTR [-16+rbp], rdi #8.5
mov rax, QWORD PTR [-16+rbp] #8.5
mov rdi, rax #8.5
call std::vector<int, std::allocator<int> >::vector() [complete object constructor] #8.5
leave #8.5
ret
push rbp#8.5
mov rbp,rsp#8.5
副rsp,16#8.5
mov QWORD PTR[-16+rbp],rdi#8.5
mov rax,QWORD PTR[-16+rbp]#8.5
mov rdi,rax#8.5
调用std::vector::vector()[完整对象构造函数]#8.5
离开#8.5
ret
虽然我同意其他人的观点,即禁用优化后查看性能几乎没有什么效果,但在这种情况下,即使禁用优化(至少在这三个编译器中)也不足以获得用于构建两个类的对象的不同代码。如果有一些编译器和/或优化设置会产生不同的结果,我想我不会感到非常惊讶,但我恐怕没有足够的雄心壮志去花更多的时间去寻找它。我怀疑你认为你看到的速度差异主要是时间差的副产品,而且不是真的
为了查看生成的结果,我稍微简化了代码,只留下以下内容:
#include <vector>
template <typename T>
struct Foo
{
std::vector<T> data_;
Foo() = default;
};
template <typename T>
struct Bar
{
std::vector<T> data_;
Bar() {};
};
int main() {
Foo<int> f;
Bar<int> b;
}
#包括
模板
结构Foo
{
std::矢量数据;
Foo()=默认值;
};
模板
结构条
{
std::矢量数据;
Bar(){};
};
int main(){
福福;
b栏;
}
然后我把它放在这里,以便于查看生成的代码
gcc 9.2似乎为两个CTOR生成了相同的代码,在这两种情况下都是这样:
push rbp
mov rbp, rsp
sub rsp, 16
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
call std::vector<int, std::allocator<int> >::vector() [complete object constructor]
nop
leave
ret
push-rbp
mov rbp,rsp
副区长,16
mov QWORD PTR[rbp-8],rdi
mov rax,QWORD PTR[rbp-8]
莫夫尔迪,拉克斯
调用std::vector::vector()[完整对象构造函数]
不
离开
ret
Clang生成的代码略有不同,但(同样)这两个类的代码相同:
push rbp
mov rbp, rsp
sub rsp, 16
mov qword ptr [rbp - 8], rdi
mov rdi, qword ptr [rbp - 8]
call std::vector<int, std::allocator<int> >::vector() [base object constructor]
add rsp, 16
pop rbp
ret
push-rbp
mov rbp,rsp
副区长,16
mov qword ptr[rbp-8],rdi
mov rdi,qword ptr[rbp-8]
调用std::vector::vector()[基本对象构造函数]
加上rsp,16
流行限制性商业惯例
ret
Intel icc几乎相同,为这两个类生成以下代码:
push rbp #8.5
mov rbp, rsp #8.5
sub rsp, 16 #8.5
mov QWORD PTR [-16+rbp], rdi #8.5
mov rax, QWORD PTR [-16+rbp] #8.5
mov rdi, rax #8.5
call std::vector<int, std::allocator<int> >::vector() [complete object constructor] #8.5
leave #8.5
ret
push rbp#8.5
mov rbp,rsp#8.5
副rsp,16#8.5
mov QWORD PTR[-16+rbp],rdi#8.5
mov rax,QWORD PTR[-16+rbp]#8.5
mov rdi,rax#8.5
调用std::vector::vector()[完整对象构造函数]#8.5
离开#8.5
ret
虽然我同意其他人的观点,即禁用优化后查看性能几乎没有什么效果,但在这种情况下,即使禁用优化(至少在这三个编译器中)也不足以获得用于构建两个类的对象的不同代码。如果有一些编译器和/或优化设置会产生不同的结果,我想我不会感到非常惊讶,但我恐怕没有足够的雄心壮志去花更多的时间寻找它。使用系统时钟
来计时不是一个好主意。@Nicolas,我对时间安排的准确性不感兴趣。我感兴趣的是,Foo可以始终比Bar有更好的性能(反之亦然)。时钟已经足够好了。你测试过优化的构建吗?否则,您的结果将毫无意义。未经优化的编译不是为性能而设计的。因此,测量未经优化的代码的性能是一种无用的娱乐形式。@n.“代词m。我想
push rbp #8.5
mov rbp, rsp #8.5
sub rsp, 16 #8.5
mov QWORD PTR [-16+rbp], rdi #8.5
mov rax, QWORD PTR [-16+rbp] #8.5
mov rdi, rax #8.5
call std::vector<int, std::allocator<int> >::vector() [complete object constructor] #8.5
leave #8.5
ret