Есть некоторая шаблонная структура данных, где в качестве массива для данных T использовался T * или std::byte * .
После множества прогонов (версия: С++ 20 с флагом -O3, компилятор Clang) бенчмарков на большом количестве данных (особенно большая разница была для типов std::is_scalar (порядка 25%), и порядка 10% для пользовательских типов) заметил, что когда в качестве массива используется T *, а не std::byte *, появляется ощутимый прирост прозводительности.
При переходе на T * с std::byte * изменились только следующие участки кода:
Инициализация массива
buffer(new (std::align_val_t(alignof(T))) std::byte[initialCapacity * sizeof(T)])
// Изменилась на
buffer(reinterpret_cast<T *>(new (std::align_val_t(alignof(T))) std::byte[initialCapacity * sizeof(T)])
И несколько сравнений
FirstComparator{}((*reinterpret_cast<T *>(&buffer[(position * sizeof(T)) * 2])), (*reinterpret_cast<T *>(&buffer[((position * 2 + 1) * sizeof(T))])))
// Поменялось на
FirstComparator{}(buffer[position * 2], buffer[position * 2 + 1])
Откуда могла возникнуть такая разница? Может быть, компилятор, зная точный тип, а не std:: byte *, делает какие-то оптимизации ?
Полагаю, что с T * у компилятора есть больше инфы (в частности, сам тип T, а не std::byte), на основе этого он делает какие-то доп. оптимизации
P.S.: посмотрел код
EASTL, там тоже, например в векторе, используется T *, а не char *