I have recently started to modernize my C++ codebase by using C++14 instead of C++11.
After replacing a single occurrence of std::unique_ptr.reset(new ...)
with std::make_unique
from C++14 I realized that my test suite (which consists of about 30 C++ test programs) ran about 50% slower.
Old C++11 code (fast):
class Foo
{
public:
Foo(size_t size)
{
array.reset(new char[size]);
}
private:
std::unique_ptr<char[]> array;
};
New C++14 code (slow):
class Foo
{
public:
Foo(size_t size)
{
array = std::make_unique<char[]>(size);
}
private:
std::unique_ptr<char[]> array;
};
Both GCC and Clang run much slower using the C++14 code with std::make_unique
. When I test both versions using valgrind it reports that both the C++11 and C++14 code use the same amount of allocations and the same amount of allocated memory and there are no memory leaks.
When I look at the generated assembly of the test programs above I have the suspicion that the C++14 version using std::make_unique
resets the memory after the allocation using memset. The C++11 version does not do this:
C++11 assembly (GCC 7.4, x64)
main:
sub rsp, 8
movsx rdi, edi
call operator new[](unsigned long)
mov rdi, rax
call operator delete[](void*)
xor eax, eax
add rsp, 8
ret
C++14 assembly (GCC 7.4, x64)
main:
push rbx
movsx rbx, edi
mov rdi, rbx
call operator new[](unsigned long)
mov rcx, rax
mov rax, rbx
sub rax, 1
js .L2
lea rax, [rbx-2]
mov edx, 1
mov rdi, rcx
cmp rax, -1
cmovge rdx, rbx
xor esi, esi
call memset
mov rcx, rax
.L2:
mov rdi, rcx
call operator delete[](void*)
xor eax, eax
pop rbx
ret
Questions:
Is initializing memory a known feature of std::make_unique
? If not what else could explain the performance slowdown I am experiencing?