Я пытаюсь создать небольшое приложение для бенчмаркинга, которое позволяет пользователю измерять время выполнения и использование памяти в программе.Измерение времени выполнения других процессов с помощью C#, нечетные результаты
Это код для измерения времени выполнения:
private static Stopwatch _stopwatch;
static void Main(string[] args]
{
_stopwatch = new Stopwatch();
//only for this test
Console.WriteLine(TimeProcess("Empty.exe"));
Console.WriteLine(TimeProcess("Sieve.exe"));
Console.ReadKey();
}
private static long TimeProcess(String name)
{
Process process = new Process();
process.StartInfo.FileName = name;
_stopwatch.Reset();
_stopwatch.Start();
process.Start();
process.WaitForExit();
_stopwatch.Stop();
return _stopwatch.ElapsedMilliseconds;
}
Чтобы увидеть, если код работает правильно, я решил осуществить «Решето Эратосфена» алгоритм. Я реализовал его дважды, один раз со встроенным секундомером, и один раз без него.
Сито
int[] numbersToTest = Enumerable.Range(0, 1000).ToArray();
int posInArray = 2;
while (numbersToTest[posInArray] != numbersToTest[numbersToTest.Length - 1])
{
numbersToTest = numbersToTest.Where(x => x % numbersToTest[posInArray] != 0 || x == numbersToTest[posInArray]).ToArray();
posInArray++;
}
TimedSieve:
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int[] numbersToTest = Enumerable.Range(0, 1000).ToArray();
int posInArray = 2;
while (numbersToTest[posInArray] != numbersToTest[numbersToTest.Length - 1])
{
numbersToTest = numbersToTest.Where(x => x % numbersToTest[posInArray] != 0 || x == numbersToTest[posInArray]).ToArray();
posInArray++;
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
Кроме того, у меня есть проект с пустым основным методом. Моя логика заключалась в том, что когда я измеряю выполнение «Сита» и вычитаю время пустого проекта, результирующее число должно быть примерно таким же, как число, измеренное «TimedSieve». Так что я начал измерение ...
Empty: 79 milliseconds
Sieve: 53 milliseconds
TimedSieve: 4 milliseconds
Очевидно, что эти результаты кажутся очень тусклыми:
- TimedSieve намного быстрее, чем как пустой проекта и решето
- Пустой проект медленнее чем сито!
Просто из любопытства я приурочил Сито и пустой проект с использованием Powershells «Measure-Command»
Sieve: 25 milliseconds
Empty: 17 milliseconds
Что-то я заметил, что тот факт, что порядок, в котором были измерены процессы под влиянием результаты, процесс, который был измерен, всегда всегда терялся. Я также заметил, что перенос начала секундомера после начала процесса, как этого
process.Start();
_stopwatch.Start();
избавившись от вышеупомянутого эффекта (Empty теперь всегда быстрее, чем решето) и получают номера, которые гораздо ближе к результаты других методов измерения
Empty: 34
Sieve: 42
При попытке решить эту проблему, я также читал, что тесты должны включать «прогрев» круглый, и я решил бенчмарка обе программы несколько раз и взять среднее, чтобы получить лучшие результаты ,
static void Main(string[] args)
{
_stopwatch = new Stopwatch();
//discard results of the first run
TimeProcess("Sieve.exe");
long sum = 0;
for (int i = 0; i < 100; i++)
{
sum += TimeProcess("Sieve.exe");
}
Console.WriteLine(sum/100);
TimeProcess("Empty.exe");
sum = 0;
for (int i = 0; i < 100; i++)
{
sum += TimeProcess("Empty.exe");
}
Console.WriteLine(sum/100);
Console.ReadKey();
}
Это избавившись от «пустого медленнее, чем сито» эффект, поэтому я решил начать секундомер перед процессом снова.
Как я могу улучшить этот код, чтобы получить достоверные результаты? Хотя цифры стали намного более разумными, они все еще медленнее, чем измерения Powershell и TimedSieve.
Вероятно, вы измеряете время ввода IO в диске, поэтому результаты являются подозрительными. Первый процесс медленнее, потому что диск должен искать, тогда как второй процесс, к которому он, скорее всего, уже ищет, и просто идет прямо. К сожалению, нет простого способа удалить этот эффект. Причина, по которой ваше второе решение (запустить его один раз, а затем запустить его 100 раз), - это то, что Windows кэширует программу в память. Если кэш невозможен (как в этом случае), он может просто загрузить программу из кеша. –
Спасибо, это похоже на разумное объяснение первых результатов, я сомневаюсь, что это входило мне в голову. – Aifu
Это часто забытое объяснение, иногда мы забываем (все мы, программисты, даже), что есть другие вещи, которые продолжаются в начале программы. Disk File IO, выделения памяти, распределения кучи и т. Д. –