Производительность system.runtime.caching - PullRequest
27 голосов
/ 01 июля 2010

Я сравнил производительность system.runtime.caching в .NET 4.0 и блоке кэширования Enterprise Library, и, к моему удивлению, он работает ужасно по сравнению при извлечении больших коллекций данных из элементов кэша.

Enterprise Libraryизвлекает 100 объектов за 0,15 мс, 10000 объектов за 0,25 мс.Это быстро и естественно для внутрипроцессного кэша, потому что на самом деле копировать данные не нужно (только ссылки).

. Кэширование .NET 4.0 извлекает 100 объектов за 25 мс, 10000 объектов за 1500 мс!Это очень медленно по сравнению с ним, и я подозреваю, что кэширование выполняется вне процесса.

Мне не хватает какой-либо опции конфигурации, например, для включения кэширования в процессе, или это блок кэширования Enterprise Libraryнеужели это намного быстрее?

Обновление

Вот мой тест:

Сначала я загружаю данные из базы данных в кеш (отдельно отбенчмарк).

Я использую таймер для методов get для измерения времени в миллисекундах:

EnterpriseLibrary Caching

Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager _cache;

public void InitCache(){
    _cache = CacheFactory.GetCacheManager("myCacheName");
}

public void Benchmark(){
    HighPerformanceTimer timer = new HighPerformanceTimer();
    timer.Start();
    myObject o = (myObject)_cache.GetData(myCacheKey);
    timer.Stop();
    Response.Write(timer.GetAsStringInMilliseconds());
}

Кэширование .NET 4.0

    System.Runtime.Caching.MemoryCache _cache;

    public void InitCache(){
        _cache = new MemoryCache("myCacheName");
    }

    public void Benchmark(){
        HighPerformanceTimer timer = new HighPerformanceTimer();
        timer.Start();
        myObject o = (myObject)_cache.Get(myCacheKey);
        timer.Stop();
        Response.Write(timer.GetAsStringInMilliseconds());
    }

Тест производительности выполняется 1000 раз, чтобы вычислить среднее время выборки объекта для обеспечения надежности теста.Таймер - это пользовательский таймер, которым я пользуюсь, любой таймер, считающий миллисекунды, должен делать.

Интересно то, что myObject имеет множество ссылок.Если бы была задействована какая-либо сериализация, я бы понял, почему производительность этого объекта отличается (например, в распределенном кэшировании), но это оба кэша в процессе, которые теоретически должны работать без каких-либо существенных отличий.

1 Ответ

8 голосов
/ 13 июля 2012

Я предполагаю, что детали содержимого или политики вашего кэша не совпадают. Не видя настройки или вставок, трудно сказать, как именно.

Несмотря на это, две библиотеки имеют разные характеристики производительности, и какая из них лучше, зависит от ситуации.

Вероятно, мой тест (код ниже) слишком прост, чтобы быть репрезентативным, но при его запуске на моей машине MemoryCache примерно в 10 раз быстрее .

class Program
{        
    const string myCacheKey = "foo";
    static ICacheManager _elCache;        
    static MemoryCache _rtCache;
    public static void InitCache()
    {            
        _elCache = CacheFactory.GetCacheManager();
        _elCache.Add(myCacheKey, new object());

        _rtCache = new MemoryCache("cache");
        _rtCache.Add(myCacheKey, new object(), new CacheItemPolicy());
    }
    public static string ElBenchmark(int n)
    {
        Stopwatch timer = new Stopwatch();
        timer.Start();
        for (int i = 0; i < n; i++)
        {
            object o = _elCache.GetData(myCacheKey);
        }
        timer.Stop();
        return timer.ElapsedTicks.ToString();
    }
    public static string RtBenchmark(int n)
    {
        Stopwatch timer = new Stopwatch();
        timer.Start();
        for (int i = 0; i < n; i++)
        {
            object o = _rtCache.Get(myCacheKey);
        }
        timer.Stop();
        return timer.ElapsedTicks.ToString();
    }
    static void Main(string[] args)
    {
        while (true)
        {
            InitCache();
            StringBuilder sb = new StringBuilder();
            System.Diagnostics.Debug.Write("EL: " + ElBenchmark(10000));
            System.Diagnostics.Debug.Write("\t");
            System.Diagnostics.Debug.Write("RT: " + RtBenchmark(10000));
            System.Diagnostics.Debug.Write("\r\n");
        }
    }
}


<?xml version="1.0"?>
<configuration>

  <configSections>
    <section name="cachingConfiguration"
         type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>
  <cachingConfiguration defaultCacheManager="MyCacheManager">
    <cacheManagers>
      <add name="MyCacheManager" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
       expirationPollFrequencyInSeconds="60"
       maximumElementsInCacheBeforeScavenging="50000"
       numberToRemoveWhenScavenging="1000"
       backingStoreName="NullBackingStore" />
    </cacheManagers>
    <backingStores>
      <add type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
       name="NullBackingStore" />
    </backingStores>
  </cachingConfiguration>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>  
</configuration>
...