2012-07-30 108 views
4

此性能測試錯誤或系統緩存正在以卓越的性能工作?
內存緩存.Net 4.0性能測試:令人驚訝的結果

這是我的結果:
[13]的相互作用的數100000:63毫秒
[14]的相互作用的數100000:139毫秒
[12]的相互作用的數100000:47毫秒
[ 15]交互次數100000:44毫秒
測試結束。

硬件: x86系列6型23步進GenuineIntel〜2992兆赫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 = "[email protected]$?_-"; 
     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<string> keys = new List<string>(); 

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

對我來說沒問題。什麼讓你懷疑結果? – Oded 2012-07-30 20:28:24

+3

這裏的實際問題是什麼?什麼是驚人的? – 2012-07-30 21:33:26

+0

我發現了非凡的表現,這讓我很懷疑。 – lsalamon 2012-07-30 21:45:07

回答

4

看起來不錯。雖然低於一秒的時間不是很可靠;你可能會遇到垃圾收集,你的電腦可能會做一些其他的一段時間,第一次JIT編譯等。

所以增加計數。這也應該使每個線程的結果更接近。

上週我做了一些測試,使其每秒達到800萬次迭代(並不是很多,但仍然)是單線程的。所以是的,PC的這些天都很快;-)

5

問題是StopWatch類不能在多核心機器上使用! (我假設你有一個多核CPU)當線程從一個內核移動到另一個內核時(即使是單線程應用程序跳轉核心),與BIOS如何處理計數器有關。

編輯:
退房 - http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx - 特別註釋部分。 還有一個stackoverflow帖子 - Multicore and thread aware .Net stopwatch?末編輯

我已搜查高和低衡量應用性能我想出的最佳方法和最可靠的是DateTime.UtcNow。獲取開始和結束時間,然後區分它們之間的差異。你必須足夠循環你的代碼才能通過低精度,但沒有其他的方法,我遇到了更多的可靠的準確性。

+2

@exacerbatedexpert - 在打電話給FUD之前,你爲什麼不研究這個問題。看看 - http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx - 和備註部分。特別指出,由於BIOS錯誤,您可能會得到不同的結果,這反過來意味着在多核心機器上使用StopWatch是沒有意義的(沒有設置線程關聯)。 – Marko 2012-08-30 05:50:38

+0

@exacerbatedexpert - (我讀過你的知識庫文章)。MSDN文章註釋部分沒有指定每個BIOS都有該錯誤,但它也沒有指定只有少數BIOS有錯誤。所以現在取決於你如何幹預所寫的內容。我認爲在備註部分的文字意味着這些錯誤廣泛存在,這就是爲什麼你不應該依賴秒錶在多核CPU上給出準確結果(沒有設置線程親和性)。在網絡上有多個帖子的人有秒錶的問題,這應該都支持我的要求... – Marko 2012-09-01 10:56:56

+2

我不知道在這種情況下StopWatch類是否是一個問題(處理器規格看起來像一個至強,但不要不知道它是否是多核心的)。但是,我在自己的代碼中肯定遇到了StopWatch類的問題,所以我建議不要使用它。問題偶爾會包括負面的時間間隔。然而,更常見的是,連續值顯然是不正確的,後面的值比先前的值小。 – 2013-01-16 23:04:20

2

在我的機器上,每個GetItem調用約爲40 ms或400 ns。

我跟蹤調試器下的調用,它在我的I7機器上每個GetItem約有2000條指令。這超出了我的預期。