I am having this issue for months now. I upgraded from entlib 4.1 to 5. My application is caching increasingly more items. At times (sometimes trice a day) the CPU hangs at 100% usage but the application stays responsive. I used dotTrace to get a snapshot when this occurs and it appears that most of the time is spent in PriorityDateComparer.Compare
. This Comparer is used only by the constructor of the System.Collections.SortedList and contains this body:
public int Compare(object x, object y)
{
CacheItem leftCacheItem = (CacheItem)unsortedItems[(string)x];
CacheItem rightCacheItem = (CacheItem)unsortedItems[(string)y];
lock (rightCacheItem)
{
lock (leftCacheItem)
{
if (rightCacheItem == null && leftCacheItem == null)
{
return 0;
}
if (leftCacheItem == null)
{
return -1;
}
if (rightCacheItem == null)
{
return 1;
}
return leftCacheItem.ScavengingPriority == rightCacheItem.ScavengingPriority
? leftCacheItem.LastAccessedTime.CompareTo(rightCacheItem.LastAccessedTime)
: leftCacheItem.ScavengingPriority - rightCacheItem.ScavengingPriority;
}
}
}
Question 1: Can we be sure that the two cache items are always locked in the same order? I don't think so, if I examine the implementation of SortedList.
Question 2: If the answer to my first question is no then how do we solve this? I see some possibilities:
- Remove locking and make sure only one thread is used.
- Place one lock on the unsortedItems collection and not on the cacheItems.
- Somehow figure out in which order to lock the items, for instance by comparing (string)x and (string)y first, and then lock them in the proper order.
- other: ...
What do you prefer?