79351818

Date: 2025-01-13 10:19:17
Score: 2
Natty:
Report link

No, the ConcurrentDictionary<K,V>.TryRemove method doesn't release all allocated memory. It releases the memory associated with the removed key (a Node), but it doesn't shrink the array where the nodes are stored. The amount of memory wasted by a partially filled ConcurrentDictionary<K,V> is significantly less than the amount of memory wasted by a partially filled Dictionary<K,V>, and that's why currently (.NET 9) the ConcurrentDictionary<K,V> is not equipped with an API similar to the Dictionary<K,V>.TrimExcess.

Adding the TrimExcess to the ConcurrentDictionary<K,V> has been proposed in this GitHub proposal, but it didn't go anywhere and it was eventually closed. Quoting from this proposal:

ConcurrentDictionary stores its data differently than does a Dictionary; the vast majority of memory it consumes is stored in nodes per element, rather than one large array.

ConcurrentDictionary._tables._buckets is a Node array, whose length can be even greater than the number of elements, and this array will not shrink when the elements are removed.

Yes, but all it stores are the node references; with Dictionary, each entry stores both the TKey and the TValue and additional state (a hash code and next link).

The references also occupy a lot of memory. On 64-bit systems, for simple key/value, e.g. ConcurrentDictionary<int, int>, a reference takes about 40% memory of a Node.

A reference is 8 bytes on 64-bit. Can you please share code for the scenario that's causing you to want such a method?

Reasons:
  • RegEx Blacklisted phrase (2.5): Can you please share code
  • Long answer (-1):
  • Has code block (-0.5):
  • Ends in question mark (2):
  • Looks like a comment (1):
  • High reputation (-2):
Posted by: Theodor Zoulias