ResolvableType#forType calls purgeUnreferencedEntries on its cache, and an additional restructure call also happens potentially on the get call to the cache. Under high contention / multithreading scenarios, lots of threads may be competing for the segment locks and doing cleanup.
Making purgeUnferencedEntries acquire a lock with tryLock and only perform the clean up if some other thread isn't already actively doing it would help here; the same behavior could be done at the segment level, where instead of acquiring the lock, tryLock is used to avoid repeating work that was likely just done. I haven't worked through the implications in detail but maybe separate methods (maybeRestructureIfNecessary) would be a safer way to add the behavior.
ResolvableType#forTypecallspurgeUnreferencedEntrieson its cache, and an additional restructure call also happens potentially on thegetcall to the cache. Under high contention / multithreading scenarios, lots of threads may be competing for the segment locks and doing cleanup.Making
purgeUnferencedEntriesacquire a lock withtryLockand only perform the clean up if some other thread isn't already actively doing it would help here; the same behavior could be done at the segment level, where instead of acquiring the lock,tryLockis used to avoid repeating work that was likely just done. I haven't worked through the implications in detail but maybe separate methods (maybeRestructureIfNecessary) would be a safer way to add the behavior.