Performance issue in NextGen ARC model - much better now
Back in 2013, I found out an implementation weakness in the implementation
of ARC weak references in the RTL.
A giant lock was freezing all threads and cores, so would decrease a lot the performance abilities of any ARC application, especially in multi thread.
I just investigated that things are now better.
Do you remember that the previous code was the following:
procedure TInstHashMap.RegisterWeakRef(Address: Pointer; Instance: Pointer); var H: Integer; Item: PInstItem; begin Lock; try H := Hash(Instance); Item := FindInstItem(Instance, H); if Item = nil then Item := AddInstItem(Instance, H); Item.RegisterWeakRef(Address); finally Unlock; end; end;
Now (in Delphi 10 Seatle), it sounds like:
procedure TInstHashMap.RegisterWeakRef(Address: Pointer; Instance: Pointer); var H, Index: Integer; Item: PInstItem; begin if not FInitialized then Initialize; H := Hash(Instance); FBuckets[H].Lock; try Item := FindInstItem(Instance, H, Index); if Item = nil then Item := AddInstItem(Instance, H, Index); finally FBuckets[H].Unlock; end; Item.RegisterWeakRef(Address); end;
As you can see, the giant lock has been replaced by a per-bucket lock.
So the giant lock has been replaced by 197 locks.
They are still using
may be an issue in some cases, in respect to native OS mutex API.
And also the fact that the lock is released, then re-acquired in
Item.RegisterWeakRef() - not optimal. A single new locked method
FBuckets[H] level would be more elegant and efficient than
this mess of nested calls, for sure.
Of course, we still prefer a per-class hash list, as implemented in mORMot zeroing weak references, instead of this global hash list.
But it is a good move, in such a critical path of the RTL!
Good to see that some part of the RTL is been polished in newer versions, about performance and potential bottlenecks.
Feedback is welcome in our forum, as usual.