簡體   English   中英

批量內存沒有碎片stl容器

[英]Bulk memory free of fragmented stl containers

目前,當我們想要破壞具有非常分散的內存分配的復雜對象的非常大的嵌套列表/映射時,我假設C ++是調用析構函數並逐個釋放內存並遞歸,這需要花費大量時間並且效率低下?

在我的情況下,我發現有時需要1分鍾或更長時間才能破壞300GB的物體。

操作系統可以殺死占用大量內存的進程,因為它只是釋放所有內存而不考慮內部邏輯進程。

我想知道是否有任何現有的C / C ++庫可以做到這一點? 提供維護id系統的自定義內存分配器? 這樣,如果我指定一個id來為給定的大型STL容器(及其元素)創建一個分配器。 當我想要破壞它時,我可以釋放分配了指定id的所有內存,並且只丟棄指向外部容器的指針(它會跳過所有的析構函數)? 就像我們可以“殺死”一個pid ......

謝謝!

這可以通過池分配器和新的放置來完成,當然你會有一些限制,比如找到池中插槽的通用大小(如果你不想要精細的粒度),但通常一個簡單的案例場景就像以下:

struct Foo {
  double x, y;
  Foo(double x, double y) { this->x = x; this->y = y; };
};

std::byte* buffer = new std::byte[sizeof(Foo) * 10];

Foo* foo1 = new(buffer) Foo(1.0, 2.0);
Foo* foo2 = new(buffer + sizeof(Foo)) Foo(1.0, 2.0);

delete[] buffer;

解釋了基本原理。 這必須采取預防措施,因為沒有人調用你的析構函數(你應該通過foo1->~Foo()手動完成)。 但是如果析構函數沒有副作用,或者您可以立即處理它們,那么標准允許您不要明確地調用它。

現在棘手的部分是,如果你正在使用STL集合,那么他們會在內部進行大量的分配來存儲他們的需求(特別是像std::mapstd::list這樣的容器)。 所以你需要編寫一個自定義allocator<T>來包裝一個有效的池方案。

如果您想要有效freeing內存,那么執行單個刪除是可行的方法。 雖然請記住,釋放內存並不是刪除調用所做的唯一事情。 它也稱為析構函數。 如果不是微不足道或不可見,您的編譯器仍然必須通過函數調用來調用它。

也就是說,盡可能使用std::vector 我已經在向量之上編寫了自定義集和映射,功能較少(沒有刪除),以獲得內存和性能。

如果你有很多小物體,比如通常需要1,2,...... 16個元素的矢量,你可以通過使用更多的內存來獲得速度。 boost小向量和其他容器可以幫助您不分配。 在算法中使用它,已經在真實世界代碼中節省了顯着的百分比(> 90%)。

最后,你不能總是贏。 如果您可以估計內存使用情況,或已經接近的情況,可以使用[ https://howardhinnant.github.io/stack_alloc.html ] ( Howard Hinnant的堆棧分配器)。 不要被名字所迷惑,你也可以在堆上分配內存。 通過一些操作,我懷疑你應該能夠改變它以接受運行時大小。 但是,它並不完美,你可以覆蓋很大一部分。

也就是說,您總是可以故意創建內存泄漏,但這可能會消除析構函數的副作用。 您可以從地圖中提取節點 ,並將它們存儲在已分配的矢量中。 這可能會躍入UB,我不是那里的專家。

哦,最后,你可以繼承標准的allocator,只覆蓋deallocate函數。 查看全局以確定是否要調用實際的deallocate。 翻轉開關,並在退出時進行內存泄漏。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM