8

このパフォーマンス テストは間違っていますか、それともシステム キャッシュが非常に優れたパフォーマンスで動作していますか?

これが私の結果です:
[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<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

4 に答える 4

5

いいね。1 秒未満のタイミングはあまり信頼できませんが。ガベージ コレクションに遭遇した可能性があります。PC がしばらくの間、最初の JIT コンパイルなどで何か他のことを行っている可能性があります。

なので回数を増やしてください。これにより、各スレッドの結果がより近くなります。

先週行ったいくつかのテストでは、シングルスレッドで 1 秒あたり 800 万回の反復が行われました (それほど多くはありませんが、それでも)。はい、最近の PC は高速です ;-)

于 2012-08-22T08:43:58.853 に答える
3

私のマシンでは、約 40 ミリ秒、または GetItem 呼び出しごとに 400 ナノ秒です。

デバッガーで呼び出しを追跡しました。私の I7 マシンでは、GetItem ごとに約 2000 命令です。それは私が期待する以上のものです。

于 2012-08-31T05:18:22.050 に答える
3

問題は、マルチコア マシンで使用できない StopWatch クラスです。(マルチコア CPU を使用していると仮定します) スレッドがあるコアから別のコアに移動するときに BIOS がそのカウンターを処理する方法に関係があります (単一のスレッド化されたアプリケーションでさえコアをジャンプします!)。

編集:
チェックアウト - http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx - 特に備考セクション。スタックオーバーフローの投稿もあります-マルチコアとスレッド対応の.Netストップウォッチ? . 編集を終了

アプリのパフォーマンスを測定するための最良の方法を高低で検索しましたが、私が思いついた最も信頼できる方法は DateTime.UtcNow です。開始時刻と終了時刻を取得し、それらの差をとります。精度の低さを乗り越えるには、コードを十分にループする必要がありますが、私が遭遇した他の方法では、より信頼性の高い精度が得られません。

于 2012-08-29T22:04:07.227 に答える