1. C++17 memory_resource 內(nèi)存池
C++17 引入了一個(gè)新的內(nèi)存資源抽象層 - memory_resource
。其主要目的是將內(nèi)存的分配和回收與具體的數(shù)據(jù)結(jié)構(gòu)解耦,從而允許開(kāi)發(fā)人員使用不同的內(nèi)存管理策略,提高內(nèi)存管理的靈活性。memory_resource
是一個(gè)基類(lèi),可以用于創(chuàng)建和配置具有不同內(nèi)存管理行為的內(nèi)存池。
1.1 memory_resource 基類(lèi)
memory_resource
是一個(gè)抽象基類(lèi),提供了三個(gè)純虛函數(shù),需要被子類(lèi)實(shí)現(xiàn):
-
do_allocate(size_t bytes, size_t alignment)
:根據(jù)指定的字節(jié)和對(duì)齊方式分配內(nèi)存。 -
do_deallocate(void* p, size_t bytes, size_t alignment)
:釋放之前分配的內(nèi)存。 -
do_is_equal(const memory_resource& other) const noexcept
:判斷兩個(gè)內(nèi)存資源是否等效。
以下是 memory_resource
基類(lèi)的一個(gè)簡(jiǎn)單實(shí)現(xiàn):
class MyMemoryResource : public std::pmr::memory_resource
{
protected:
void* do_allocate(size_t bytes, size_t alignment) override
{
return ::operator new(bytes);
}
void do_deallocate(void* p, size_t bytes, size_t alignment) override
{
::operator delete(p);
}
bool do_is_equal(const memory_resource& other) const noexcept override
{
return this == &other;
}
};
1.2 內(nèi)存資源的使用
要使用 memory_resource
,通常需要通過(guò)它來(lái)創(chuàng)建一些容器。例如,我們可以用 memory_resource
創(chuàng)建一個(gè) std::pmr::vector
:
MyMemoryResource myMemoryResource;
std::pmr::vector<int> vec(&myMemoryResource);
這樣,vec
就會(huì)使用 myMemoryResource
來(lái)進(jìn)行內(nèi)存的分配和回收。
1.3 全局和本地內(nèi)存資源
C++ 提供了兩種內(nèi)存資源:全局內(nèi)存資源和本地內(nèi)存資源。全局內(nèi)存資源是通過(guò) std::pmr::get_default_resource()
獲得的,所有沒(méi)有指定內(nèi)存資源的 std::pmr
對(duì)象都會(huì)使用它。本地內(nèi)存資源是創(chuàng)建 std::pmr
對(duì)象時(shí)指定的,它會(huì)覆蓋全局內(nèi)存資源。
例如:
std::pmr::vector<int> vec; // 使用全局內(nèi)存資源
std::pmr::vector<int> vec(&myMemoryResource); // 使用本地內(nèi)存資源
1.4 其他內(nèi)存資源類(lèi)型
除了用戶自定義的內(nèi)存資源,C++ 還提供了幾種預(yù)定義的內(nèi)存資源:
-
std::pmr::new_delete_resource()
:用new
和delete
進(jìn)行內(nèi)存分配和回收。 -
std::pmr::null_memory_resource()
:任何嘗試分配內(nèi)存的操作都會(huì)拋出std::bad_alloc
異常。 -
std::pmr::unsynchronized_pool_resource
和std::pmr::synchronized_pool_resource
:內(nèi)存池資源,分別為線程不安全和線程安全版本。
下面的章節(jié)將會(huì)繼續(xù)介紹這兩種內(nèi)存池資源。
2. struct unsynchronized_pool_resource
unsynchronized_pool_resource
是 C++17 中 std::pmr::memory_resource
的一種實(shí)現(xiàn)。這種內(nèi)存資源管理方式以?xún)?nèi)存池的形式存在,其主要的優(yōu)勢(shì)在于減少內(nèi)存分配和回收的開(kāi)銷(xiāo)。這種資源被設(shè)計(jì)為線程不安全,所以對(duì)于多線程環(huán)境需要開(kāi)發(fā)者自己進(jìn)行管理和同步。
2.1 unsynchronized_pool_resource 的基本原理
unsynchronized_pool_resource
內(nèi)部維護(hù)了一系列的內(nèi)存池,每個(gè)內(nèi)存池負(fù)責(zé)管理一定大小范圍的內(nèi)存塊。當(dāng)需要分配內(nèi)存時(shí),內(nèi)存池資源會(huì)根據(jù)請(qǐng)求的大小選擇一個(gè)適當(dāng)?shù)膬?nèi)存池,并從中分配一個(gè)內(nèi)存塊。如果對(duì)應(yīng)的內(nèi)存池沒(méi)有可用的內(nèi)存塊,那么內(nèi)存池資源會(huì)從上游內(nèi)存資源那里獲取更多的內(nèi)存。
2.2 unsynchronized_pool_resource 的使用
要使用 unsynchronized_pool_resource
,需要?jiǎng)?chuàng)建一個(gè) unsynchronized_pool_resource
對(duì)象,并將其作為其他 std::pmr
對(duì)象的內(nèi)存資源。以下是一個(gè)例子:
std::pmr::unsynchronized_pool_resource pool;
std::pmr::vector<int> vec(&pool);
在這個(gè)例子中,vec
將使用 pool
來(lái)進(jìn)行內(nèi)存的分配和回收。
2.3 unsynchronized_pool_resource 的配置
unsynchronized_pool_resource
具有一些可配置的參數(shù),包括最大和最小塊大小、最大塊數(shù)等。這些參數(shù)可以通過(guò) std::pmr::pool_options
結(jié)構(gòu)體來(lái)設(shè)置,后面的章節(jié)將詳細(xì)介紹這個(gè)結(jié)構(gòu)體。
2.4 unsynchronized_pool_resource 的線程安全性
如其名所示,unsynchronized_pool_resource
是線程不安全的。如果在多線程環(huán)境中使用 unsynchronized_pool_resource
,則必須確保每個(gè)線程都使用自己的 unsynchronized_pool_resource
,或者通過(guò)某種同步機(jī)制(如互斥鎖)來(lái)保護(hù) unsynchronized_pool_resource
。
雖然這增加了使用 unsynchronized_pool_resource
的復(fù)雜性,但是由于避免了同步的開(kāi)銷(xiāo),unsynchronized_pool_resource
在某些場(chǎng)景下可能會(huì)比同步的內(nèi)存池更高效。
2.5 unsynchronized_pool_resource 與 new/delete 的對(duì)比
相比于使用 new
和 delete
進(jìn)行內(nèi)存管理,unsynchronized_pool_resource
主要的優(yōu)勢(shì)在于減少了內(nèi)存分配和回收的開(kāi)銷(xiāo)。特別是對(duì)于頻繁分配和回收小塊內(nèi)存的場(chǎng)景,使用 unsynchronized_pool_resource
可以顯著提高性能。
此外,由于 unsynchronized_pool_resource
可以回收并重用內(nèi)存塊,因此它還可以減少內(nèi)存碎片,從而提高內(nèi)存利用率。
3. pool_options 內(nèi)存池配置
pool_options
是 C++17 中用于配置 unsynchronized_pool_resource
和 synchronized_pool_resource
的結(jié)構(gòu)體。它提供了一些參數(shù),可以用于調(diào)整內(nèi)存池的行為,以適應(yīng)不同的應(yīng)用場(chǎng)景。
3.1 pool_options 的參數(shù)
pool_options
結(jié)構(gòu)體包括以下幾個(gè)參數(shù):
-
max_blocks_per_chunk
:每個(gè)塊中最多可以包含的塊數(shù)量。這個(gè)參數(shù)用于限制內(nèi)存池從上游內(nèi)存資源一次性獲取的內(nèi)存量。如果設(shè)置為 0,則表示沒(méi)有限制。 -
largest_required_pool_block
:要求內(nèi)存池能夠處理的最大塊大小。這個(gè)參數(shù)用于確定內(nèi)存池應(yīng)該管理哪些大小的內(nèi)存塊。
以下是一個(gè)例子:
std::pmr::pool_options options;
options.max_blocks_per_chunk = 1024;
options.largest_required_pool_block = 512;
3.2 pool_options 的使用
要使用 pool_options
,需要在創(chuàng)建 unsynchronized_pool_resource
或 synchronized_pool_resource
時(shí)將其作為參數(shù)傳入。以下是一個(gè)例子:
std::pmr::pool_options options;
options.max_blocks_per_chunk = 1024;
options.largest_required_pool_block = 512;
std::pmr::unsynchronized_pool_resource pool(options);
在這個(gè)例子中,pool
將根據(jù) options
中的參數(shù)來(lái)進(jìn)行內(nèi)存的管理。
3.3 pool_options 的影響
通過(guò)調(diào)整 pool_options
中的參數(shù),可以影響內(nèi)存池的行為,從而優(yōu)化內(nèi)存的使用。
例如,如果知道應(yīng)用程序會(huì)頻繁地分配和回收一定大小的內(nèi)存塊,可以通過(guò)設(shè)置 largest_required_pool_block
來(lái)讓內(nèi)存池專(zhuān)門(mén)處理這些內(nèi)存塊,從而提高內(nèi)存的利用率。
同樣,如果知道應(yīng)用程序會(huì)分配大量的內(nèi)存塊,可以通過(guò)增加 max_blocks_per_chunk
來(lái)減少?gòu)纳嫌蝺?nèi)存資源獲取內(nèi)存的次數(shù),從而減少內(nèi)存管理的開(kāi)銷(xiāo)。
總的來(lái)說(shuō),pool_options
提供了一種靈活的方式來(lái)配置內(nèi)存池,使其能夠根據(jù)應(yīng)用程序的需求提供最優(yōu)的內(nèi)存管理策略。
4. memory_resource
我們已經(jīng)在第一部分對(duì) memory_resource
做了基礎(chǔ)的介紹。memory_resource
是 C++17 中提供的一種內(nèi)存資源抽象,它是所有內(nèi)存資源的基類(lèi)。在這一部分,我們將深入探討 memory_resource
的幾個(gè)關(guān)鍵的方法。
4.1 memory_resource::allocate()
這個(gè)方法是用戶用來(lái)從 memory_resource
請(qǐng)求內(nèi)存的接口。它接收兩個(gè)參數(shù):需要的字節(jié)數(shù)和對(duì)齊要求。然后,它將調(diào)用 do_allocate
方法來(lái)分配內(nèi)存。
4.2 memory_resource::deallocate()
這個(gè)方法用于將之前分配的內(nèi)存歸還給 memory_resource
。它接收三個(gè)參數(shù):要?dú)w還的內(nèi)存指針、該內(nèi)存塊的大小和對(duì)齊要求。然后,它將調(diào)用 do_deallocate
方法來(lái)歸還內(nèi)存。
4.3 memory_resource::is_equal()
這個(gè)方法用于判斷兩個(gè) memory_resource
是否相等。在默認(rèn)情況下,兩個(gè) memory_resource
是相等的,當(dāng)且僅當(dāng)它們是同一個(gè)對(duì)象。
4.4 memory_resource::do_allocate(), memory_resource::do_deallocate(), memory_resource::do_is_equal()
這三個(gè)方法是 memory_resource
的純虛函數(shù),必須由子類(lèi)實(shí)現(xiàn)。具體的內(nèi)存分配和回收行為,以及兩個(gè)內(nèi)存資源的比較方式,取決于這三個(gè)方法的實(shí)現(xiàn)。
例如,unsynchronized_pool_resource
和 synchronized_pool_resource
就是通過(guò)這三個(gè)方法實(shí)現(xiàn)了自己的內(nèi)存管理策略。
4.5 memory_resource 的使用方式
memory_resource
通常不直接使用,而是作為創(chuàng)建其他 std::pmr
對(duì)象時(shí)的參數(shù),例如 std::pmr::vector
或 std::pmr::string
。
以下是一個(gè)例子:
std::pmr::synchronized_pool_resource pool;
std::pmr::vector<int> vec(&pool);
在這個(gè)例子中,vec
將使用 pool
來(lái)進(jìn)行內(nèi)存的分配和回收。
memory_resource
提供了一個(gè)通用的內(nèi)存資源接口,讓你可以根據(jù)應(yīng)用程序的需求來(lái)自定義內(nèi)存管理策略。通過(guò)使用 memory_resource
,你可以創(chuàng)建出對(duì)內(nèi)存使用更有效率的數(shù)據(jù)結(jié)構(gòu)。
5. unsynchronized_pool_resource 線程不安全
unsynchronized_pool_resource
是一種為 C++17 標(biāo)準(zhǔn)庫(kù)提供的內(nèi)存資源類(lèi),用于從預(yù)分配的內(nèi)存池中進(jìn)行內(nèi)存分配和回收。關(guān)鍵的一點(diǎn)是,unsynchronized_pool_resource
不提供線程安全的保證。這是它與 synchronized_pool_resource
的主要區(qū)別。我們接下來(lái)詳細(xì)討論這一點(diǎn)。
5.1 何為線程不安全
"線程不安全"的意思是,如果同一個(gè) unsynchronized_pool_resource
實(shí)例被多個(gè)線程同時(shí)使用,沒(méi)有其他的同步機(jī)制(例如互斥鎖)來(lái)保護(hù)這個(gè)實(shí)例,那么可能會(huì)導(dǎo)致數(shù)據(jù)競(jìng)爭(zhēng)和未定義的行為。也就是說(shuō),多個(gè)線程不能同時(shí)對(duì)一個(gè) unsynchronized_pool_resource
實(shí)例進(jìn)行讀寫(xiě)。
5.2 unsynchronized_pool_resource 的線程不安全
由于 unsynchronized_pool_resource
不提供內(nèi)部的同步機(jī)制,所以在多線程環(huán)境中使用 unsynchronized_pool_resource
需要特別小心。以下是兩種常見(jiàn)的使用方式:
-
每個(gè)線程都使用自己的
unsynchronized_pool_resource
實(shí)例。這種方式的好處是,由于沒(méi)有競(jìng)爭(zhēng),每個(gè)線程的內(nèi)存操作都可以盡可能快。但是,這種方式可能會(huì)導(dǎo)致內(nèi)存的使用不夠高效,因?yàn)槊總€(gè)線程都需要預(yù)分配自己的內(nèi)存池。 -
使用一個(gè)共享的
unsynchronized_pool_resource
實(shí)例,并使用外部的同步機(jī)制(例如互斥鎖)來(lái)保護(hù)這個(gè)實(shí)例。這種方式的好處是,可以更高效地利用內(nèi)存,因?yàn)樗械木€程都從同一個(gè)內(nèi)存池中獲取和回收內(nèi)存。但是,這種方式可能會(huì)導(dǎo)致性能下降,因?yàn)榫€程需要等待其他線程釋放鎖。
5.3 如何處理 unsynchronized_pool_resource 的線程不安全
處理 unsynchronized_pool_resource
的線程不安全的最佳方式取決于應(yīng)用程序的具體需求。如果性能是最重要的因素,并且可以接受更高的內(nèi)存使用率,那么每個(gè)線程都使用自己的 unsynchronized_pool_resource
實(shí)例可能是最好的選擇。如果內(nèi)存效率是最重要的因素,并且可以接受更低的性能,那么使用一個(gè)共享的 unsynchronized_pool_resource
實(shí)例和外部的同步機(jī)制可能是最好的選擇。
整體上,unsynchronized_pool_resource
提供了一種高效的內(nèi)存管理方式,但是在多線程環(huán)境中使用時(shí)需要注意線程安全問(wèn)題。通過(guò)正確地使用 unsynchronized_pool_resource
,你可以根據(jù)應(yīng)用程序的需求來(lái)平衡內(nèi)存效率和性能。
6. synchronized_pool_resource 線程安全
synchronized_pool_resource
是 C++17 中提供的一種內(nèi)存資源類(lèi),和 unsynchronized_pool_resource
類(lèi)似,都是為了提供高效的內(nèi)存分配和回收服務(wù)。但是,synchronized_pool_resource
的主要區(qū)別在于它是線程安全的。
6.1 什么是線程安全
在多線程編程中,如果一個(gè)函數(shù)、函數(shù)庫(kù)或者類(lèi)可以在多線程環(huán)境下被同時(shí)調(diào)用,而不產(chǎn)生錯(cuò)誤的結(jié)果或者未定義行為,那么我們就稱(chēng)之為線程安全的。簡(jiǎn)單來(lái)說(shuō),線程安全就是在多線程環(huán)境下保證結(jié)果的正確性和狀態(tài)的一致性。
6.2 synchronized_pool_resource 的線程安全
synchronized_pool_resource
是線程安全的,它提供了內(nèi)部同步機(jī)制來(lái)確保多個(gè)線程可以同時(shí)對(duì)它進(jìn)行內(nèi)存分配和回收操作。也就是說(shuō),多個(gè)線程可以共享一個(gè) synchronized_pool_resource
實(shí)例,而無(wú)需擔(dān)心數(shù)據(jù)競(jìng)爭(zhēng)或者未定義行為。
這個(gè)特性讓 synchronized_pool_resource
成為在多線程環(huán)境下處理內(nèi)存管理的理想選擇。
6.3 如何使用 synchronized_pool_resource
使用 synchronized_pool_resource
非常簡(jiǎn)單,和 unsynchronized_pool_resource
的用法類(lèi)似。你可以在創(chuàng)建 synchronized_pool_resource
的實(shí)例時(shí),傳入一個(gè) pool_options
參數(shù)來(lái)配置內(nèi)存池,然后使用 allocate()
和 deallocate()
方法來(lái)分配和回收內(nèi)存。
以下是一個(gè)例子:
std::pmr::pool_options options;
options.max_blocks_per_chunk = 1024;
options.largest_required_pool_block = 512;
std::pmr::synchronized_pool_resource pool(options);
// 從 pool 中分配內(nèi)存
void* p = pool.allocate(100);
// 將內(nèi)存歸還給 pool
pool.deallocate(p, 100);
在這個(gè)例子中,即使有多個(gè)線程同時(shí)執(zhí)行上述代碼,synchronized_pool_resource
也能保證每次 allocate()
和 deallocate()
操作的正確性。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-538712.html
synchronized_pool_resource
提供了一種線程安全、高效的內(nèi)存管理方式。通過(guò)使用 synchronized_pool_resource
,你可以在多線程環(huán)境下進(jìn)行安全、快速的內(nèi)存分配和回收,從而提高應(yīng)用程序的性能。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-538712.html
到了這里,關(guān)于【C++內(nèi)存管理】?jī)?nèi)存池的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!