簡體   English   中英

有效地重用 std::unordered_map

[英]reusing std::unordered_map efficiently

我在我的程序中管理相對較小的臨時字典。 我的問題:重用它們(使用后使用mymap.clear() )比delete舊的並創建new的更有效嗎?

此外,這些字典目前實現為std::unordered_map<std::string, int> 這是有效的,但如果(根據上述使用模式)另一個容器( stl或不是)更可取,我會毫不猶豫地切換此實現。

你配置了嗎? 因為現在這只是很多猜測。

考慮std::unordered_map上的newdelete只是增加了實例化/拆除容器本身的開銷。 std::unordered_map::clear內部仍然會在它持有的每個對象上調用delete ,以便調用它的析構函數。 可能涉及到一個奇特的分配器,它為容器元素實現了一個相同大小的槽池,以節省內存管理開銷。

根據所包含對象的復雜性,使用普通的std::vector可能更明智,也可能更明智

你必須分析你的開銷在哪里。 但更重要的是,只有完成工作,如果這是你的程序的一部分,導致統計上顯着放緩。 您應該選擇易於閱讀和實現清晰而不是微優化。

不幸的是, .clear()沒有任何性能優勢,重用只是獲得一個新的基於節點的容器,它的工作量幾乎相同。

如果您知道字典的最大大小,並且它相當小,請考慮為節點使用自定義分配器。

這樣,您可能會使事情變得更緊湊並節省分配開銷。

除此之外,避免在標准庫之外分配數千個單獨節點的其他容器也是可能的。

這是可行的,但如果(根據上述使用模式)另一個容器(stl 或不是)更可取,我會毫不猶豫地切換此實現。

好的選擇開始。 如果你想嘗試別的東西:

  • 考慮前綴樹
  • 考慮來自其他庫的其他哈希映射,例如abseil

使用真實數據衡量真實場景中的性能,以查看替代方案是否值得使用。

至少對於 GCC, std::unordered_map<std::string, int>在任何時間點都有如下動態分配:

  • 1 個存儲桶數組的分配,每個存儲桶將迭代器(可能實現為指針)保存到一個單向鏈接的節點列表中(通常在您的峰值元素數的 1 倍到 2 倍之間),或者當沒有元素散列到該存儲桶時的哨兵迭代器狀態
  • #elements 分配:有一個帶有 next 指針的節點,一個哈希值(是的,它保存了它!),以及std::stringint數據
  • #keys 長於 15:任何std::string對於短字符串優化(文本內容直接存儲在std::string對象中)來說太長,將有一個指向動態分配的文本緩沖區的指針

當您執行.clear() ,后兩類分配將被釋放。 當容器本身被破壞時,只完成一次額外的釋放。

所以,我不希望保留unordered_map很大的性能改進。

如果您關心性能,請更仔細地查看您的數據。 字符串長度有上限嗎? 如果有並且它不是很大(例如 8 或 16 字節),您可以使用開放尋址又名封閉散列獲取一個哈希表,其中鍵和值直接存儲在存儲桶中,因此只有一個動態分配正在進行。 這可能會給你帶來很大的性能提升(但總是衡量)。

暫無
暫無

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

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