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)
Défini dans l'en-tête <memory_resource>
class monotonic_buffer_resource : public std:: pmr :: memory_resource ;
(depuis C++17)

La classe std::pmr::monotonic_buffer_resource est une classe de ressource mémoire à usage spécial qui libère la mémoire allouée uniquement lorsque la ressource est détruite. Elle est conçue pour des allocations mémoire très rapides dans des situations où la mémoire est utilisée pour construire quelques objets puis est libérée en une seule fois.

monotonic_buffer_resource peut être construit avec un tampon initial. S'il n'y a pas de tampon initial, ou si le tampon est épuisé, des tampons supplémentaires sont obtenus d'une ressource mémoire amont fournie lors de la construction. La taille des tampons obtenus suit une progression géométrique.

monotonic_buffer_resource n'est pas thread-safe.

Table des matières

Fonctions membres

construit une monotonic_buffer_resource
(fonction membre publique)
[virtuel]
détruit une monotonic_buffer_resource , libérant toute la mémoire allouée
(fonction membre publique virtuelle)
operator=
[supprimé]
l'opérateur d'affectation par copie est supprimé. monotonic_buffer_resource n'est pas copiable par affectation
(fonction membre publique)
Fonctions membres publiques
libère toute la mémoire allouée
(fonction membre publique)
retourne un pointeur vers la ressource mémoire amont
(fonction membre publique)
Fonctions membres protégées
[virtuel]
alloue de la mémoire
(fonction membre protégée virtuelle)
[virtuel]
opération sans effet
(fonction membre protégée virtuelle)
[virtuel]
compare pour l'égalité avec une autre std::pmr::memory_resource
(fonction membre protégée virtuelle)

Exemple

Le programme mesure le temps de création de listes doublement chaînées volumineuses en utilisant les allocateurs suivants :

  • allocateur standard par défaut,
  • allocateur pmr par défaut,
  • allocateur pmr avec ressource monotone mais sans tampon mémoire explicite,
  • allocateur pmr avec ressource monotone et tampon mémoire externe (sur la pile).
#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; // suffisant pour contenir tous les nœuds
        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 (allocateur std par défaut) : " << t1 << " sec; t1/t1: " << t1/t1 << '\n'
              << "t2 (allocateur pmr par défaut) : " << t2 << " sec; t1/t2: " << t1/t2 << '\n'
              << "t3 (pmr alloc  no buf): " << t3 << " sec; t1/t3: " << t1/t3 << '\n'
              << "t4 (pmr alloc et buf): " << t4 << " sec; t1/t4: " << t1/t4 << '\n';
}

Sortie possible :

t1 (alloc std par défaut) : 0.720 sec ; t1/t1 : 1.000
t2 (alloc pmr par défaut) : 0.915 sec ; t1/t2 : 0.787
t3 (alloc pmr sans buf) : 0.370 sec ; t1/t3 : 1.945
t4 (alloc pmr avec buf) : 0.247 sec ; t1/t4 : 2.914