0

In the thread When immutable collections are preferable then concurrent it is stated that immutable collections may be slower but they save memory. How is it possible if every change of immutable collection results in creating new object?

I understand that concurrent collection refers to one object and it uses synchronization primitives. So how the immutable collection can save more memory than concurrent collection?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
helpME1986
  • 933
  • 3
  • 12
  • 26
  • I don't particularly like any of the answers in that linked question... The main point is, when accessing an immutable object, you can be sure that it isn't going to change under you. You don't need to hold a lock while reading, you don't need to make any defensive copies, etc. When reading a concurrent collection, you need to make sure that everything is safe if the collection changes while you're reading it, which means it needs to use locks and other tricks internally. There's a trade-off there of course. – canton7 Aug 27 '21 at 15:06
  • 1
    "*How is it possible if every change of immutable collection results in creating new object?*" -- that isn't entirely true. The immutable collections are carefully structured so that if you modify a collection, you will get a new, changed collection, but it will make use of large parts of the data allocated for the original collection. But yes, there willbe a cost, which is why the question talks about using immutable structures for data which is read often, but written rarely – canton7 Aug 27 '21 at 15:07

1 Answers1

1

An immutable collection can save memory only under very specific circumstances. Mainly when your application's logic requires that snapshots of the collection must be taken frequently. Imagine for example that one workflow of your application has to take a snapshot of the collection every few seconds and do some work with it, while other workflows keep mutating the collection. That's the scenario where the immutable collections shine. Taking a snapshot of a concurrent collection is expensive in all aspects (CPU/memory/contention), while taking a snapshot of an immutable collection is essentially free. The immutable collections by definition have snapshot semantics. The only thing required in order to convert an immutable collection to a snapshot is a memory barrier, so that the thread requesting the snapshot can be sure that it will see the latest and fully initialized value stored in the field or variable. This memory barrier can be imposed by declaring the field as volatile, or by reading the variable with the Volatile.Read method. Example:

var snapshot = Volatile.Read(ref _users);

As a side note, it is also possible to update an immutable collection without taking a lock, by using Interlocked techniques. There is even a class available (ImmutableInterlocked) that simplifies greatly these operations. Example:

ImmutableInterlocked.Update(ref _users, x => x.Add(user));
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104