Namespaces
Variants

std::pmr:: monotonic_buffer_resource

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
Definido en el encabezado <memory_resource>
class monotonic_buffer_resource : public std:: pmr :: memory_resource ;
(desde C++17)

La clase std::pmr::monotonic_buffer_resource es una clase de recurso de memoria de propósito especial que libera la memoria asignada solo cuando se destruye el recurso. Está diseñada para asignaciones de memoria muy rápidas en situaciones donde la memoria se utiliza para construir algunos objetos y luego se libera toda de una vez.

monotonic_buffer_resource puede construirse con un búfer inicial. Si no hay búfer inicial, o si el búfer se agota, se obtienen búferes adicionales de un recurso de memoria ascendente suministrado durante la construcción. El tamaño de los búferes obtenidos sigue una progresión geométrica.

monotonic_buffer_resource no es seguro para subprocesos.

Contenidos

Funciones miembro

construye un monotonic_buffer_resource
(función miembro pública)
[virtual]
destruye un monotonic_buffer_resource , liberando toda la memoria asignada
(función miembro pública virtual)
operator=
[deleted]
el operador de asignación de copia está eliminado. monotonic_buffer_resource no es asignable por copia
(función miembro pública)
Funciones miembro públicas
libera toda la memoria asignada
(función miembro pública)
devuelve un puntero al recurso de memoria ascendente
(función miembro pública)
Funciones miembro protegidas
[virtual]
asigna memoria
(función miembro protegida virtual)
[virtual]
sin operación
(función miembro protegida virtual)
[virtual]
compara para igualdad con otro std::pmr::memory_resource
(función miembro protegida virtual)

Ejemplo

El programa mide el tiempo de creación de enormes listas doblemente enlazadas utilizando los siguientes asignadores de memoria:

  • asignador estándar predeterminado,
  • asignador pmr predeterminado,
  • pmr asignador con recurso monótono pero sin búfer de memoria explícito,
  • pmr asignador con recurso monótono y búfer de memoria externo (en pila).
#include <array>
#include <chrono>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <list>
#include <memory_resource>
template<typename Func>
auto benchmark(Func test_func, int iterations)
{
    const auto start = std::chrono::system_clock::now();
    while (iterations-- > 0)
        test_func();
    const auto stop = std::chrono::system_clock::now();
    const auto secs = std::chrono::duration<double>(stop - start);
    return secs.count();
}
int main()
{
    constexpr int iterations{100};
    constexpr int total_nodes{2'00'000};
    auto default_std_alloc = [total_nodes]
    {
        std::list<int> list;
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    auto default_pmr_alloc = [total_nodes]
    {
        std::pmr::list<int> list;
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    auto pmr_alloc_no_buf = [total_nodes]
    {
        std::pmr::monotonic_buffer_resource mbr;
        std::pmr::polymorphic_allocator<int> pa{&mbr};
        std::pmr::list<int> list{pa};
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    auto pmr_alloc_and_buf = [total_nodes]
    {
        std::array<std::byte, total_nodes * 32> buffer; // suficiente para contener todos los nodos
        std::pmr::monotonic_buffer_resource mbr{buffer.data(), buffer.size()};
        std::pmr::polymorphic_allocator<int> pa{&mbr};
        std::pmr::list<int> list{pa};
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    const double t1 = benchmark(default_std_alloc, iterations);
    const double t2 = benchmark(default_pmr_alloc, iterations);
    const double t3 = benchmark(pmr_alloc_no_buf , iterations);
    const double t4 = benchmark(pmr_alloc_and_buf, iterations);
    std::cout << std::fixed << std::setprecision(3)
              << "t1 (allocador std predeterminado): " << t1 << " seg; t1/t1: " << t1/t1 << '\n'
              << "t2 (asignador pmr predeterminado): " << t2 << " seg; t1/t2: " << t1/t2 << '\n'
              << "t3 (pmr alloc  no buf): " << t3 << " seg; t1/t3: " << t1/t3 << '\n'
              << "t4 (pmr alloc and buf): " << t4 << " seg; t1/t4: " << t1/t4 << '\n';
}

Salida posible:

t1 (default std alloc): 0.720 seg; t1/t1: 1.000
t2 (default pmr alloc): 0.915 seg; t1/t2: 0.787
t3 (pmr alloc  no buf): 0.370 seg; t1/t3: 1.945
t4 (pmr alloc and buf): 0.247 seg; t1/t4: 2.914