2010-07-01 19 views
28

He comparado el rendimiento de system.runtime.caching en .NET 4.0 y Enterprise Library Caching Block y, para mi sorpresa, tiene un rendimiento terrible en comparación cuando se obtienen grandes colecciones de datos de elementos de caché.Rendimiento de system.runtime.caching

Enterprise Library obtiene 100 objetos en aproximadamente 0,15ms, 10000 objetos en aproximadamente 0,25ms. Esto es rápido y natural para una memoria caché en proceso porque en realidad no es necesario copiar datos (solo referencias).

¡El caché de .NET 4.0 obtiene 100 objetos en aproximadamente 25 ms, 10000 objetos en aproximadamente 1500 ms! Esto es terriblemente lento en comparación y me hace sospechar que el almacenamiento en caché se realiza fuera de proceso.

¿Se está perdiendo alguna opción de configuración, por ejemplo, para habilitar el almacenamiento en memoria caché en proceso, o el Enterprise Library Caching Block realmente es mucho más rápido?

actualización

Aquí está mi punto de referencia:

En primer lugar, cargar los datos de la base de datos en la memoria caché (separada de la referencia).

debo utilizar un temporizador en torno a los métodos get para medir el tiempo en milisegundos:

EnterpriseLibrary almacenamiento en caché

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 Almacenamiento en caché

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

El punto de referencia es ejecutado 1000 veces para calcular el tiempo promedio para buscar el objeto para asegurar confiabilidad de la prueba. El temporizador es un temporizador personalizado que uso, cualquier temporizador que milisegundos debe hacer.

Lo interesante es que el "myObject" tiene numerosas referencias. Si hubiera alguna serialización involucrada, entendería por qué el rendimiento difiere para este objeto (como en el almacenamiento en caché distribuido), pero estas son cachés en proceso que teóricamente deberían funcionar sin muchas diferencias importantes.

+0

¿Está utilizando MemoryCache o comparó su propia implementación? De acuerdo con msdn MemoryCache es inproc. – ata

+0

Estoy usando MemoryCache, sin configuraciones específicas. – Herber

+0

¿Puede mostrarnos su punto de referencia? –

Respuesta

8

Supongo que los detalles de sus contenidos o políticas de caché no son los mismos. Sin ver la configuración o las inserciones, es difícil decir exactamente cómo.

Independientemente, las dos bibliotecas tienen diferentes características de rendimiento, y cuál es mejor depende claramente de la situación.

Probablemente mi prueba (código a continuación) es demasiado simple para ser representativa, pero con ella ejecutándose en mi máquina, MemoryCache es aproximadamente 10x más rápido.

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> 
Cuestiones relacionadas