Для лабораторной работы нужно измерить время выполнения нескольких операций. Код: StartTime = Environment.TickCount for (int i = 0 i < 2499 i++) { LQL.Rem() } ResultTime = Environment.TickCount - StartTime public class LinkedStackLarge { LinkedList _LinkedStack = new LinkedList() public LargeData Rem() { LargeData data = _LinkedStack.Last() _LinkedStack.RemoveFirst() return data } } Код работает, но ResultTime в конце равно 0. Это нормально?
Ответ Измерение времени операции — на самом деле сложный момент, тут есть много тонкостей. Первая тонкость — JIT warm-up: когда метод исполняется в первый раз, происходит JIT-компиляция кода этого метода. Поэтому чтобы получить правильное время, необходимо перед измерением выполнить измеряемый код «вхолостую». Следующая тонкость: при запуске из-под отладчика JIT-компилятор даже в Release mode оптимизирует ваш код не очень агрессивно, чтобы в отладчике всё ещё были видны нужные переменные и стек вызовов. Запускайте ваши тесты из-под командной строки вне Visual Studio. Следующая тонкость: если ваш измеряемый метод не производит побочных эффектов и не возвращает значения, или возвращаемое значение игнорируется, то оптимизатор может выбросить его вызов. Поэтому обязательно выводите возвращаемое значение на экран. Следующая тонкость: метод может быть очень быстрым, и сумманое время выполнения может оказаться в пределах разрешения используемого вами таймера. Для того, чтобы реально измерить его скорость, нужно выполнить его N раз, и суммарное время поделить на N. Число N проще всего подобрать экспериментально. Следующая тонкость: различные таймеры имеют различное разрешение. Лучше брать более точный таймер. Я, например, использую Stopwatch, о котором говорит @Denis Bubnov в своём ответе. Следующая тонкость: выполнение может быть прервано различными внешними событиями. Например, системный планировщик потоков может отобрать квант времени у вашего потока, в результате измеренное значение будет больше, чем реальное время пробега метода. Или сборщик мусора может заморозить ваш поток. Поэтому имеет смысл проводить измерения несколько раз, и отбрасывать результаты, которые статистически слишком далеко отстоят от среднего значения. Следующая тонкость: различные системные кеши. Например, если ваш код читает файл, то после первого чтения файл окажется в кеше операционной системы, и последующие выполнения того же метода будут быстрее. Поэтому в таком случае каждая новая итерация должна читать новый файл.
Практически, учитывать эти штуки в своём коде каждый раз лень. Поэтому имеет смысл воспользоваться фреймворком для бенчмарков. Например, можно использовать BenchmarkDotNet. В этом случае ваш код будет выглядеть так: class Program { static void Main(string[] args) { var summary = BenchmarkRunner.Run() Console.ReadKey() } } public class Tester { [Benchmark] public void Test() { for (int i = 0 i < 2499 i++) { LQL.Rem() } } }