Как я могу измерить производительность HashTable в C #? - PullRequest
1 голос
/ 20 августа 2009

Я играю с коллекциями C # и решил написать быстрый тест для измерения производительности разных коллекций.

Мой тест производительности выглядит так:

int numOps= (put number here);
long start, end, numTicks1, numTicks2;
float ratio;

start = DateTime.Now.Ticks;

for(int i = 0; i < numOps; i++)
{
  //add two elements to collection #1
  //remove one element from collection #1
}

end = DateTime.Now.Ticks;

numTicks1 = end - start;


start = DateTime.Now.Ticks;

for(int i = 0; i < numOps; i++)
{
  //add two elements to collection #2
  //remove one element from collection #2
}

end = DateTime.Now.Ticks;

numTicks2 = end - start;

ratio = (float)numTicks2/(float)numTicks1;

Затем я сравниваю значение отношения, используя разные Коллекции и разные значения для numOps, чтобы увидеть, как они сравниваются.

Проблема иногда в том, что когда я использую достаточно маленькое число (numOps = 500), результаты теста между Hashtable и List носят эпизодический характер (другими словами, это бросок монеты, который быстрее). Кто-нибудь может объяснить, почему это так?

РЕДАКТИРОВАТЬ: Спасибо всем! Секундомер работает как шарм.

Ответы [ 4 ]

8 голосов
/ 20 августа 2009

попробуйте взглянуть на класс StopWatch вместо использования DateTime

этот пример прямо из MSDN

    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();
    Thread.Sleep(10000); //your for loop
    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

    // Format and display the TimeSpan value.
    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
    Console.WriteLine(elapsedTime, "RunTime");
4 голосов
/ 20 августа 2009

Я бы начал с опробования таймера с более высоким разрешением.

На SO уже есть несколько вопросов и ответов о таймерах.

Вот один ответ со списком доступных вам вариантов.

В частности, проверьте System.Diagnostics.Stopwatch .

2 голосов
/ 20 августа 2009

Правильный способ измерения времени для диагностики состоит в том, чтобы многократно выполнять код многократно (так что общее время во много раз превышает разрешение любого используемого вами механизма синхронизации), а затем делить на число итераций, чтобы получить точное время оценить.

Секундомер возвращает время, которое не квантуется за 15 мс, поэтому оно, очевидно, больше подходит для хронирования событий.

0 голосов
/ 20 августа 2009

Я использовал следующий код для проверки производительности Dictionary с использованием трех различных реализаций GetHash:

    class TestGetHash
    {
        class First
        {
            int m_x;
        }
        class Second
        {
            static int s_allocated = 0;
            int m_allocated;
            int m_x;
            public Second()
            {
                m_allocated = ++s_allocated;
            }
            public override int GetHashCode()
            {
                return m_allocated;
            }
        }
        class Third
        {
            int m_x;
            public override int GetHashCode()
            {
                return 0;
            }
        }

        internal static void test()
        {
            testT<First>(100, 1000);
            testT<First>(1000, 100);
            testT<Second>(100, 1000);
            testT<Second>(1000, 100);
            testT<Third>(100, 100);
            testT<Third>(1000, 10);
        }

        static void testT<T>(int objects, int iterations)
            where T : new()
        {
            System.Diagnostics.Stopwatch stopWatch = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < iterations; ++i)
            {
                Dictionary<T, object> dictionary = new Dictionary<T, object>();
                for (int j = 0; j < objects; ++j)
                {
                    T t = new T();
                    dictionary.Add(t, null);
                }
                for (int k = 0; k < 100; ++k)
                {
                    foreach (T t in dictionary.Keys)
                    {
                        object o = dictionary[t];
                    }
                }
            }
            stopWatch.Stop();
            string stopwatchMessage = string.Format("Stopwatch: {0} type, {1} objects, {2} iterations, {3} msec", typeof(T).Name, objects, iterations, stopWatch.ElapsedMilliseconds);
            System.Console.WriteLine(stopwatchMessage);

            stopWatch = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < iterations; ++i)
            {
                Dictionary<T, object> dictionary = new Dictionary<T, object>();
                for (int j = 0; j < objects; ++j)
                {
                    T t = new T();
                    dictionary.Add(t, null);
                }
            }
            stopWatch.Stop();
            stopwatchMessage = string.Format("Stopwatch (fill dictionary): {0} type, {1} objects, {2} iterations, {3} msec", typeof(T).Name, objects, iterations, stopWatch.ElapsedMilliseconds);
            System.Console.WriteLine(stopwatchMessage);

            {
                Dictionary<T, object> dictionary = new Dictionary<T, object>();
                for (int j = 0; j < objects; ++j)
                {
                    T t = new T();
                    dictionary.Add(t, null);
                }
                stopWatch = System.Diagnostics.Stopwatch.StartNew();
                for (int i = 0; i < iterations; ++i)
                {
                    for (int k = 0; k < 100; ++k)
                    {
                        foreach (T t in dictionary.Keys)
                        {
                            object o = dictionary[t];
                        }
                    }
                }
                stopWatch.Stop();
                stopwatchMessage = string.Format("Stopwatch (read from dictionary): {0} type, {1} objects, {2} iterations, {3} msec", typeof(T).Name, objects, iterations, stopWatch.ElapsedMilliseconds);
                System.Console.WriteLine(stopwatchMessage);
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...