内存缓存.Net 4.0性能测试:惊人的结果

此性能测试是错误的还是系统缓存正在以卓越的性能运行?

这是我的结果:
[13]交互次数100000:63毫秒
[14]交互次数100000:139毫秒
[12]交互次数100000:47毫秒
[15]交互次数100000:44毫秒
测试结束。

硬件:x86 Family 6 Model 23 Stepping GenuineIntel~2992 Mhz 3.327 MB,5.1.2600 Service Pack 3

using System; using System.Collections.Generic; using System.Runtime.Caching; using System.Diagnostics; using System.Threading; namespace CacheNet40 { public class CacheTest { private ObjectCache cache; public CacheTest() { cache = MemoryCache.Default; } public void AddItem(CacheItem item, double span) { CacheItemPolicy cp = new CacheItemPolicy(); cp.SlidingExpiration.Add(TimeSpan.FromMinutes(span)); cache.Add(item, cp); } public Object GetItem(string key) { return cache.Get(key); } } class Program { private static CacheTest Cache = new CacheTest(); private static string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789!@$?_-"; private static int counter = 0; private static readonly object locker = new object(); static string CreateRandomString(int passwordLength, int idx) { char[] chars = new char[passwordLength]; Random rd = new Random((int)DateTime.Now.Ticks + idx); for (int i = 0; i < passwordLength; i++) { chars[i] = allowedChars[rd.Next(0, allowedChars.Length)]; } return new string(chars); } private static void CacheAccessTes() { int span = 5; string key; string data; int itens = 1000; int interactions = 100000; int cont = 0; int index = 0; List keys = new List(); lock (locker) { counter++; } cont = itens; //populates it with data in the cache do { key = CreateRandomString(127, Thread.CurrentThread.ManagedThreadId + cont); keys.Add(key); data = CreateRandomString(156000, Thread.CurrentThread.ManagedThreadId + cont + 1); CacheItem ci = new CacheItem(key, data); Cache.AddItem(ci, span); cont--; } while (cont > 0); cont = interactions; index = 0; //test readings Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); do { Object ci = Cache.GetItem(keys[index]); ci = null; index++; if (index == itens) { index = 0; } cont--; } while (cont > 0); stopWatch.Stop(); lock (locker) { counter--; } string outstring = String.Format("[{0}] number of interactions {1} : {2} milliseconds", Thread.CurrentThread.ManagedThreadId, interactions, stopWatch.ElapsedMilliseconds ); Console.WriteLine(outstring); } static void Main(string[] args) { for (int threads = 0; threads < 4; threads++) { Thread thread = new Thread(new ThreadStart(CacheAccessTes)); thread.Start(); } Thread.Sleep(1000); while (true) { lock (locker) { if (counter == 0) break; } Thread.Sleep(100); } Console.WriteLine("End of test."); Console.ReadLine(); } } } 

看起来不错。 虽然低于一秒的时间不是很可靠; 你可能遇到了垃圾收集,你的电脑可能会做一些其他事情,第一次JIT编译等。

所以增加计数。 这也应该使每个线程的结果更加接近。

我上周做的一些测试使得每秒800万次迭代(不是很多,但仍然是)单线程。 所以是的,这些天PC很快;-)

问题是StopWatch类不能在多核机器上使用! (我假设你有一个多核CPU)当一个线程从一个核心移动到另一个核心时,BIOS处理该计数器的方式(甚至一个线程应用程序跳转核心!)。

编辑:
退房 – http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx – 特别是备注部分。 还有一个stackoverflowpost – 多核和线程感知.Net秒表? 。 结束编辑

我已经搜索了从高到低的最佳方法来衡量应用程序性能,而我提出的最可靠的是DateTime.UtcNow。 获取开始和结束时间,然后区分它们。 你必须循环你的代码足以超越低精度,但我遇到的其他方法没有提供更可靠的准确性。

在我的机器上,每个GetItem调用大约40毫秒或400毫秒。

我在调试器下跟踪调用,在我的I7机器上每个GetItem大约有2000个指令。 这比我预期的要多。