Пользовательский распределитель, новый / удалить против malloc () / free () - PullRequest
0 голосов
/ 13 октября 2019

Итак, этот вопрос возник в основном благодаря сообщениям, подобным этим:
Почему new () / delete () медленнее, чем malloc () / free ()?

РассмотримВы оказались в ситуации, когда:

  • вы в основном работаете с простыми старыми типами данных, и вам приходится выполнять много операций выделения / освобождения
  • вы работаете с непрерывными блоками памяти
  • по какой-то причине производительность действительно имеет значение ...


Идея состоит в том, чтобы создать новый класс распределителя, который может "выбирать" междудва метода, а именно new и malloc().

Допустим, вы будете использовать std::allocator, если ваш тип не является типом POD,
и использовать такой распределитель, как описано здесь: https://en.cppreference.com/w/cpp/named_req/Allocator (Mallocator)
, если ваш тип равен типу POD

А теперь, чтобы выбрать свой класс распределителя, вы будете использовать что-то вроде этого:

namespace meta
{

    template<bool, typename T>
    struct Allocator_Impl;

    template<typename T>
    struct Allocator_Impl<true, T>
    {
        using type = Mallocator<T>;
    };

    template<typename T>
    struct Allocator_Impl<false, T>
    {
        using type = std::allocator<T>;
    };

    template<typename T>
    struct is_trivially_allocateable
    {
        using type = typename
        std::conjunction<std::is_trivial<T>,
                         std::is_standard_layout<T>>::type;

        constexpr static inline bool value = type::value;
    };
}

template<typename T>
struct Allocator : public meta::Allocator_Impl<meta::is_trivially_allocateable<T>::value, T>
{};



После этого реализовать наш "умный?"Контейнер мы можем просто унаследовать от старого доброго vector класса, например. Допустим, этот вектор находится где-то в другом пространстве имен, например, sna:

namespace sna
{
    template<typename T> using allocTy = typename Allocator<T>::type;


    template<typename T, class Alloc = allocTy<T>>
    class vector : public std::vector<T, Alloc>
    {
    public:
        typedef typename std::vector<T, Alloc>::size_type size_type;
        typedef T value_type;
        typedef Alloc allocator;
        typedef std::vector<value_type, allocator> parent;

        vector() : parent() {}
        vector(const size_type n) :
            parent(n)

        ... implement other constructors if needed ...
    };
}



После этого - просто чтобы убедиться - я тоже сравнил распределениераз и придумал:

Распределение 100000000 double:
Продолжительность с вектором нормалей: 281528400 нс.
Продолжительность с вектором заказчиков: 1990600 нс.



Для теста я использовал этот фрагмент кода:

std::chrono::system_clock::time_point start, stop;

const size_t size = 100000000;
std::cout << "Allocating " << size << " doubles:" << std::endl;

start = std::chrono::high_resolution_clock::now();
std::vector<double> new_data(size);
stop = std::chrono::high_resolution_clock::now();
std::cout << "Duration with normal vector: ";
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count() << " ns." << std::endl;

start = std::chrono::high_resolution_clock::now();
sna::vector<double> malloc_data(size);
stop = std::chrono::high_resolution_clock::now();
std::cout << "Duration with custom vector: ";
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count() << " ns." << std::endl;



Для этого теста я использовал флаг оптимизации -O2.
Итакдля меня vector, использующий класс Mallocator, более чем в сто раз быстрее, чем класс std::allocator, что, на мой взгляд, является значительным приростом производительности.

Но все это в стороне:
Считается ли что-то вроде этого "трюка" плохой практикой, или, если ситуация описана выше, можете ли вы использовать что-то подобное безопасно? Было бы другое лучшее решение, или это просто не стоило бы усилий, и я должен вместо этого придерживаться типа std::vector?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...