.net - Rendimiento de system.runtime.caching
performance .net-4.0 (1)
He comparado el rendimiento de system.runtime.caching en .NET 4.0 y Enterprise Library Caching Block y, para mi sorpresa, funciona terriblemente en comparación cuando se obtienen grandes colecciones de datos de elementos de caché.
Enterprise Library obtiene 100 objetos en aproximadamente 0,15 ms, 10000 objetos en aproximadamente 0,25 ms. Esto es rápido y natural para una memoria caché en proceso porque en realidad no es necesario copiar datos (solo referencias).
¡El almacenamiento en 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.
¿Me falta alguna opción de configuración, por ejemplo, para habilitar el almacenamiento en caché en proceso, o el Enterprise Library Caching Block realmente es mucho más rápido?
Actualizar
Aquí está mi punto de referencia:
Primero, cargo los datos de la base de datos a la memoria caché (separada de la referencia).
Utilizo un temporizador alrededor de los métodos get para medir el tiempo en milisegundos:
Almacenamiento en caché de EnterpriseLibrary
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());
}
Caché de .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());
}
El punto de referencia se ejecuta 1000 veces para calcular el tiempo promedio para recuperar el objeto y garantizar la fiabilidad 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.
Supongo que los detalles de los contenidos o las políticas de tu caché no son los mismos. Sin ver la configuración o las inserciones, es difícil decir exactamente cómo.
De todos modos, 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) sea demasiado simple para ser representativa, pero con esto ejecutándose en mi máquina, MemoryCache es aproximadamente 10 veces 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>