2012-06-22 2 views
0

У меня эта проблема уже несколько месяцев. Я обновил от entlib 4.1 до 5. Мое приложение кэширует все больше предметов. Время от времени (иногда трижды в день) процессор зависает при 100% использовании, но приложение остается отзывчивым. Я использовал dotTrace для получения моментального снимка, когда это происходит, и кажется, что большую часть времени тратится на PriorityDateComparer.Compare. Это Comparer используется только конструктору System.Collections.SortedList и содержит это тело:EntLib 5 Кэширование - подозрительный тупик - процессор стоит на 100%

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; 
     } 
    } 
} 

Вопрос 1: Можем ли мы быть уверены, что два элемента кэша всегда заперт в том же порядке? Я так не думаю, если я изучу реализацию SortedList.

Вопрос 2: Если ответ на мой первый вопрос: нет, тогда как мы это разрешим? Я вижу некоторые возможности:

  1. Удалить блокировку и убедиться, что используется только одна резьба.
  2. Поместите один замок в коллекцию unsortedItems, а не на cacheItems.
  3. Как-то выяснить, в каком порядке заблокировать элементы, например, сначала сравнив (string) x и (string) y, а затем заблокируйте их в правильном порядке.
  4. другие: ...

Что вы предпочитаете?

+0

Хорошо, это не тупик. Заглядывая ближе в след: есть только один поток, вызывающий компаратор. Взглянув в код: перед использованием компаратора в кешмангере помещается блокировка. Я убежден, что этот код не выполняется одновременно. Глядя снова на след: большинство времени в Сравнить занято System.Collections.HashTable.get_Item (o). Таким образом, этот компаратор используется для сортировки HashTable. Совсем не лучшая практика: [можно сортировать хэш-таблицу] (http://stackoverflow.com/questions/675759/is-it-possible-to-sort-a-hashtable). –

ответ

0

Я изменил компаратор так, что ему не нужно для поиска элементов кэша:

int IComparer<CacheItem>.Compare(CacheItem leftCacheItem, CacheItem rightCacheItem) 
    { 
    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; 
     } 
    } 
    } 

И в Microsoft.Practices.EnterpriseLibrary.Caching.ScavengerTask я изменил метод вызова в соответствии с:

private static SortedList SortItemsForScavenging(Hashtable unsortedItemsInCache) 
    { 
    return new SortedList(unsortedItemsInCache, new PriorityDateComparer(unsortedItemsInCache)); 
    } 

в

private static List<CacheItem> SortItemsForScavenging(Hashtable unsortedItemsInCache) 
    { 
    List<CacheItem> cacheValues = new List<CacheItem>(unsortedItemsInCache.Values.Cast<CacheItem>()); 
    cacheValues.Sort(new PriorityDateComparer()); 
    return cacheValues; 
    } 
Смежные вопросы