Недавно я начал модернизировать свою кодовую базу C++, используя C++ 14 вместо C++ 11.
После замены единственного вхождения std::unique_ptr.reset(new...)
с std::make_unique
из C++ 14 я понял, что мой тестовый набор (который состоит из около 30 C++ тестовых программ) составил около 50% помедленнее.
Старый C++ 11 код (быстрый):
class Foo
{
public:
Foo(size_t size)
{
array.reset(new char[size]);
}
private:
std::unique_ptr<char[]> array;
};
Новый код C++ 14 (медленный):
class Foo
{
public:
Foo(size_t size)
{
array = std::make_unique<char[]>(size);
}
private:
std::unique_ptr<char[]> array;
};
Как GCC, так и Clang работают намного медленнее, используя код C++ 14 с std::make_unique
. Когда я тестирую обе версии с использованием valgrind, он сообщает, что оба кода C++ 11 и C++ 14 используют одинаковое количество распределений и одинаковое количество выделенной памяти, и утечек памяти нет.
Когда я смотрю на сгенерированную сборку тестовых программ выше, у меня возникает подозрение, что версия C++ 14 с использованием std::make_unique
сбрасывает память после выделения с использованием memset. Версия C++ 11 не делает этого:
C++ 11 сборка (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 сборка (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
Вопросы:
Является ли инициализация памяти известной функцией std::make_unique
? Если не то, что еще может объяснить замедление производительности, которое я испытываю?