Каков наилучший способ определить, сколько времени требуется для выполнения кода?

Я пытаюсь определить, какой подход к удалению строки является быстрее.

Я просто получаю начало и конец и показываю разницу.

Но результаты настолько варьируются, например. как показано ниже, один и тот же метод может принимать от 60 мс до 231 мс.

Что такое лучший метод получения более точных результатов?

alt text http://www.deviantsart.com/upload/1q4t3rl.png

using System;
using System.Collections;
using System.Collections.Generic;

namespace TestRemoveFast
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int j = 0; j < 10; j++)
            {
                string newone = "";
                List<string> tests = new List<string>();
                for (int i = 0; i < 100000; i++)
                {
                    tests.Add("{http://company.com/Services/Types}ModifiedAt");
                }

                DateTime start = DateTime.Now;
                foreach (var test in tests)
                {
                    //newone = ((System.Xml.Linq.XName)"{http://company.com/Services/Types}ModifiedAt").LocalName;
                    newone = Clean(test);
                }

                Console.WriteLine(newone);
                DateTime end = DateTime.Now;
                TimeSpan duration = end - start;
                Console.WriteLine(duration.ToString());
            }

            Console.ReadLine();
        }

        static string Clean(string line)
        {
            int pos = line.LastIndexOf('}');
            if (pos > 0)
                return line.Substring(pos + 1, line.Length - pos - 1);
                //return line.Substring(pos + 1);
            else
                return line;
        }
    }
}

Ответ 1

Вы должны использовать System.Diagnostics.Stopwatch, и вам может потребоваться рассмотреть большой образец. Например, повторите этот тест примерно как 10 000 раз и усредните результаты. Если вы думаете об этом с научной точки зрения, это имеет смысл. Чем больше образец, тем лучше. Вы можете вырезать множество случаев кросс таким образом и действительно увидеть, что такое производительность ядра.

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

Ответ 2

Три простых заметки:

  1. Используйте System.Diagnostics.Stopwatch.

  2. Не профилируйте свой код на одном входе миллион раз. Попробуйте найти ожидаемое распределение входов и профиль по этому вопросу. Это профиль реального вклада, а не лабораторный вклад.

  3. Запустите метод Clean один раз перед входом в цикл профилирования, чтобы исключить время JITting. Иногда это важно.

Из них примечания 1. и 2. являются наиболее важными.

Ваши результаты профилирования не имеют смысла, если вы не используете таймер высокого разрешения. Обратите внимание, что мы не рассчитываем, что Усэйн Болт использует водяные часы.

Ваши результаты профилирования не имеют смысла, если вы не тестируете на реальных данных. Обратите внимание, что при краш-тестах машины столкнутся с другими автомобилями со скоростью 35 миль в час, а не со стенами из зефира со скоростью 5 миль в час.

Таким образом:

// expectedInput is string[1000000]
// populate expectedInput with real-world input
Clean(expectedInput[0]);
Stopwatch sw = new Stopwatch();
sw.Restart();          //So you dont have to call sw.Reset()
for (int i = 0; i < 1000000; i++) {
    string t = Clean(expectedInput[i]);
}
sw.Stop();
Console.WriteLine(sw.Elapsed);

Одна сложная нота:

Если вам действительно нужно выполнить профилирование, приобретите профилировщик, такой как ANTS.

Ответ 3

Вы можете использовать класс Stopwatch.

Секундомер измеряет прошедшее время на подсчет таймеров в базовом таймер. Если установленный поддержка оборудования и операционной системы счетчик производительности с высоким разрешением, то класс Секундомера использует это счетчик для измерения прошедшего времени.

var sw = new Stopwatch();

sw.Start();
// ...
sw.Stop();

Ответ 4

Если вас беспокоит только тестирование его в вашем собственном коде... используйте System.Diagnostics.Stopwatch

Я обычно предпочитаю нарушать эту вещь из своего кода и использовать истинный Profiler, например RedGate Performance Profiler

Ответ 5

Там много активности происходит под капотом ОС, что, скорее всего, испортит ваши измерения времени. Чтобы улучшить точность измеренных времен, вы должны выполнять тесты несколько раз и удалять наименьшее и наибольшее время из окончательных результатов. Такой подход исключит большинство внешних факторов, которые могут повлиять на время выполнения кода и в большинстве случаев будут служить вам хорошо. Класс Stopwatch используется для измерения времени, поскольку он намного точнее, чем при использовании DateTime.

Вы можете легко создать тестовый класс для автоматизации этого процесса. Я опубликовал один из таких классов в своем блоге. Он может сравнить производительность двух фрагментов/алгоритмов кода С#. Все, что вам нужно сделать, это переопределить методы Method1 и Method2, поместив там фрагменты кода, которые вы хотите протестировать, и используйте тестовый класс следующим образом:

Test test = new CustomTest();
Console.WriteLine("\n==============================");
Console.WriteLine(test.Execute());
Console.WriteLine("==============================\n");

Ответ 6

Возможно, вам придется применить некоторые статистические методы, чтобы сгладить дисперсию. Попробуйте запустить один и тот же фрагмент кода 1000 раз, а затем возьмите среднее время и сравните его. В симуляциях обычно используются какие-то методы для "очистки" чисел, и это один из них.

Ответ 7

Как правило: не смотрите на время работы по экрану, а время процессора, затрачиваемое на процесс, чтобы определить, как долго он работает. Особенно для вещей, которые являются просто вычислением, это намного надежнее, потому что на него не будут влиять другие процессы, запущенные одновременно.

Ответ 8

Проблема со всеми основанными на времени подходами заключается в том, что вы никогда не знаете, что вы делаете. Вы можете, понимаете ли вы это или нет, включите в свое время:

  • задерживается, когда o/s предварительно запускает ваш процессор;
  • Контекстное переключение
  • останавливается, пока программа ждет данных;
  • и многое другое.

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

В вашем конкретном случае вы должны стремиться к гораздо более длительным исполнению; когда ваше время будет второстепенным, o/s крайне вероятно повредит вам. Итак, запустите 10 ^ 6 итераций и используйте среднее значение за достаточное количество прогонов, чтобы дать вам осмысленный расчет среднего значения и дисперсии. И убедитесь, что если вы примете такой подход, вы не будете непреднамеренно ускорять второе испытание, если данные уже загружены после окончания первого испытания. Вы должны убедиться, что каждое из испытаний 10 ^ 6 делает именно то, что делает первое испытание.

Удачи

Марк

Ответ 9

Мне нужно будет рекомендовать высокопрофилировщик, включенный в Visual Studio Team Suite или Development Edition (или предстоящий Visual Studio 2010 Premium или Ultimate - лучший способ. Он очень настраиваемый, чрезвычайно мощный, мертвый, простой в использовании, очень быстрый и работает как с собственным, так и с управляемым кодом. Я не знаком с рабочим процессом ANTS, но это, по-видимому, еще один вариант. Без сомнения, использование профилировщика является единственным вариантом для разработчика, который связан с их производительностью приложений. Нет замены, и вы действительно не можете заставить коммерческого разработчика работать над производительностью, которая серьезно отнеслась бы к профилировщику.

Однако, если вас интересуют измерения для одного из следующих, у вас может не быть доступа к профилю, и в этом случае класс секундомера может стать основой для вашей методики измерения:

  • Студент или любитель, заинтересованный в выполнении своих проектов (коммерческий профайлер может быть недоступен по финансовым причинам).
  • В публично выпущенном приложении вы можете захотеть, чтобы временные разделы кода, которые выполнялись в потоке пользовательского интерфейса и отображали статистику, могли быть уверены, что операции никогда не вызовут заметных задержек для любого из ваших пользователей. Команда Office использовала такой метод с огромным успехом (любой Outlook 2007 SP2?), И я знаю, что команда Visual Studio имеет этот код, по крайней мере, в версии 2010 года.

Ответ 10

Вы также можете использовать log4net, просто добавив log.Info("Тест"), где вы хотите отслеживать материал, и вы найдете всю свою информацию и время, когда строка была выполнена в 2018-12-13 10:02:16,704 [9] INFO Hms.Domain.Concrete.RoomsRepository [(null)] - Test файле, например: 2018-12-13 10:02:16,704 [9] INFO Hms.Domain.Concrete.RoomsRepository [(null)] - Test Подробнее об этом здесь: https://www.infoworld.com/article/3120909/application-development/how-to-work -с-log4net-в-c.html