【问题标题】:Performance of system.runtime.cachingsystem.runtime.caching 的性能
【发布时间】:2011-03-10 14:20:42
【问题描述】:

我比较了 .NET 4.0 和 Enterprise Library Caching Block 中 system.runtime.caching 的性能,令我惊讶的是,它在从缓存项中获取大型数据集合时表现得非常糟糕。

企业库在大约 0.15 毫秒内获取 100 个对象,在大约 0.25 毫秒内获取 10000 个对象。这对于进程内缓存来说是快速且自然的,因为实际上不需要复制数据(仅引用)。

.NET 4.0 缓存在大约 25 毫秒内获取 100 个对象,在大约 1500 毫秒内获取 10000 个对象!相比之下,这非常慢,这让我怀疑缓存是在进程外完成的。

我是否缺少某些配置选项,例如启用进程内缓存,或者企业库缓存块真的快得多?

更新

这是我的基准:

首先,我将数据从数据库加载到缓存中(与基准测试分开)。

我在 get 方法周围使用了一个计时器来测量时间(以毫秒为单位):

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

.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”有很多引用。如果涉及任何序列化,我会理解为什么该对象的性能会有所不同(例如在分布式缓存中),但这些都是进程内缓存,理论上应该可以正常工作,根本没有太多重大差异。

【问题讨论】:

  • 您是在使用 MemoryCache 还是对自己的实现进行基准测试?根据msdn MemoryCache 是inproc。
  • 我使用的是MemoryCache,没有任何具体配置。
  • 你应该使用Stopwatch类。
  • 我认为你的测试一定有问题。使用 MSDN 中的 Hi Perf 时间(它查询性能计数器),从 .Net 4 内存缓存中检索 10K 次枚举平均需要 0.007 毫秒,10K 次检索需要 7.44 毫秒。
  • " 100 个对象在大约 0.15 毫秒内,10000 个对象在大约 0.25 毫秒内" - 这里的危险信号是在循环中调用相同的代码应该大致呈线性缩放,但事实并非如此。通话次数是原来的 100 倍,只需要多花 66% 的时间。此外,您不应该在循环中创建新的计时器对象并编写响应。

标签: .net performance caching .net-4.0 enterprise-library


【解决方案1】:

我的猜测是您的缓存内容或策略的详细信息不一样。没有看到设置或插入,很难确切地说出如何。

不管怎样,这两个库的性能特点是不同的,哪一个更好显然要视情况而定。

可能我的测试(下面的代码)太简单而无法代表,但是在我的机器上运行它后,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>

【讨论】:

    猜你喜欢
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    • 2015-04-10
    • 1970-01-01
    相关资源
    最近更新 更多