Weak references and their zeroing is managed in Delphi NextGen through a global hash table, with a global lock, see Arnaud Bouchez take on it:
Performance-issue-in-NextGen-ARC-model [1]
Also apart from the global locking which itself is bad enough, there are a couple further performance issues:
- If the locks are really through TMonitor, rather than through OS-supported critical sections, it’ll induce an extra slowdown. Under Windows 32 & 64, TMonitor.Enter/Exit is IME about 2 to 2.5 times slower than Enter/LeaveCriticalSection in low contention situations, and 10 to 20 times slower in cases of high contentions (weak references in a multi-threaded applications would thus be hit particularly hard)
- Since all references are managed in a single hash list for the whole application, you’re bound to take a noteworthy hit from the hash list itself (especially if it is based on TDictionary<>, rather than being a dedicated implementation)
There are several ways around that situation, the first is to maintain a list per-class, as is done in mORMot [2], which will spread the locking and reduce the list maintenance overhead. Another way around is to do away with weak references entirely and collect reference cycles with a dedicated GC [3], which is what Python does [4], and what DWScript does [5] (more modestly) as well. This has the benefit of removing the error-prone weak reference qualification from the code, without incurring the stalls a full GC has (see wikipedia article [3] links) and is concurrency-friendly.