std::pmr:: monotonic_buffer_resource
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Public member functions | ||||
| Protected member functions | ||||
|
Definiert im Header
<memory_resource>
|
||
|
class
monotonic_buffer_resource
:
public
std::
pmr
::
memory_resource
;
|
(seit C++17) | |
Die Klasse
std::pmr::monotonic_buffer_resource
ist eine spezielle Speicherressourcenklasse, die den allokierten Speicher nur freigibt, wenn die Ressource zerstört wird. Sie ist für sehr schnelle Speicherallokationen in Situationen vorgesehen, in denen Speicher zum Aufbau einiger Objekte verwendet wird und dann auf einmal freigegeben wird.
monotonic_buffer_resource
kann mit einem anfänglichen Puffer konstruiert werden. Falls kein anfänglicher Puffer vorhanden ist oder der Puffer erschöpft ist, werden zusätzliche Puffer von einem
upstream memory resource
bezogen, das bei der Konstruktion bereitgestellt wird. Die Größe der bezogenen Puffer folgt einer geometrischen Progression.
monotonic_buffer_resource
ist nicht threadsicher.
Inhaltsverzeichnis |
Memberfunktionen
konstruiert einen
monotonic_buffer_resource
(öffentliche Elementfunktion) |
|
|
[virtual]
|
zerstört einen
monotonic_buffer_resource
und gibt allen allokierten Speicher frei
(virtuelle öffentliche Elementfunktion) |
|
operator=
[deleted]
|
Kopierzuweisungsoperator ist gelöscht.
monotonic_buffer_resource
ist nicht kopierzuweisbar
(öffentliche Elementfunktion) |
Öffentliche Elementfunktionen |
|
|
gibt allen allokierten Speicher frei
(öffentliche Elementfunktion) |
|
|
gibt einen Zeiger auf die vorgelagerte Speicherressource zurück
(öffentliche Elementfunktion) |
|
Geschützte Elementfunktionen |
|
|
[virtual]
|
allokiert Speicher
(virtuelle geschützte Elementfunktion) |
|
[virtual]
|
No-Op (keine Operation)
(virtuelle geschützte Elementfunktion) |
|
[virtual]
|
vergleicht auf Gleichheit mit einem anderen
std::pmr::memory_resource
(virtuelle geschützte Elementfunktion) |
Beispiel
Das Programm misst die Zeit zur Erstellung umfangreicher doppelt verketteter Listen unter Verwendung der folgenden Allokatoren:
- Standard-Allokator (Standard),
-
Standard-
pmr-Allokator, -
pmr-Allokator mit monotoner Ressource aber ohne expliziten Speicherpuffer, -
pmr-Allokator mit monotoner Ressource und externem Speicherpuffer (auf dem Stack).
#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 **Erklärung:** - HTML-Tags und Attribute wurden unverändert beibehalten - C++-spezifische Begriffe (`std::chrono::system_clock::now`) wurden nicht übersetzt - Die ursprüngliche Formatierung wurde vollständig erhalten - Die Link-Struktur bleibt funktional identisch(); while (iterations-- > 0) test_func(); const auto stop = std::chrono::system_clock::now **Erklärung:** - HTML-Tags und Attribute wurden unverändert beibehalten - C++-spezifische Begriffe (`std::chrono::system_clock::now`) wurden nicht übersetzt - Die ursprüngliche Formatierung wurde vollständig erhalten - Die Link-Struktur bleibt funktional identisch(); 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; // ausreichend, um alle Knoten aufzunehmen 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 (default std alloc): " << t1 << " Sek.; t1/t1: " << t1/t1 << '\n' << "t2 (Standard-PMR-Allokator): " << t2 << " Sek.; t1/t2: " << t1/t2 << '\n' << "t3 (pmr alloc no buf): " << t3 << " sec; t1/t3: " << t1/t3 << '\n' << "t4 (pmr alloc und buf): " << t4 << " Sek.; t1/t4: " << t1/t4 << '\n'; }
Mögliche Ausgabe:
t1 (default std alloc): 0.720 Sek.; t1/t1: 1.000 t2 (default pmr alloc): 0.915 Sek.; t1/t2: 0.787 t3 (pmr alloc no buf): 0.370 Sek.; t1/t3: 1.945 t4 (pmr alloc and buf): 0.247 Sek.; t1/t4: 2.914