Содержание
При разработке различных программ иногда бывает необходимо измерить точное время какой-либо операции, например, узнать сколько времени требуется на загрузку данных из файла, запись в базу данных и так далее. Сегодня мы рассмотрим то, как измерить время выполнения операции в C#, используя стандартные средства и возможности языка.
System. Diagnostics
Пространство имен System.Diagnostics
содержит классы, позволяющие нашим приложениям взаимодействовать с журналами событий, системными процессами и счётчиками производительности. В числе прочего, это пространство имен содержит класс под названием Stopwatch
, который можно в своих приложениях C# использовать для точного измерения затраченного времени. Именно об этом классе мы сегодня и поговорим.
Простой пример использования Stopwatch
Для начала, рассмотрим простой пример использования класса Stopwatch
для измерения затраченного времени на выполнение операции.
namespace StopwatchExample { class Program { static void Main(string[] args) { //создаем объект Stopwatch stopwatch = new Stopwatch(); //засекаем время начала операции stopwatch.Start(); //выполняем какую-либо операцию for (int i = 0; i < 10001; i++) { Console.WriteLine(i); } //останавливаем счётчик stopwatch.Stop(); //смотрим сколько миллисекунд было затрачено на выполнение Console.WriteLine(stopwatch.ElapsedMilliseconds); } } }
Чтобы измерить время выполнения операции в C# нам необходимо выполнить несколько простых шагов:
- Создать объект класса
Stopwatch
; - Выполнить метод
Start()
для того, чтобы засечь время начала операции; - Выполнить метод
Stop()
для того, чтобы засечь время окончания операции; - Воспользоваться одним из свойств объекта для получения данных о затраченном на выполнение операции времени.
В примере использовано свойство ElapsedMilliseconds
, которое позволяет получить количество миллисекунд, затраченных на выполнение операции. Рассмотрим какие ещё есть свойства и методы у класса Stopwatch
.
Stopwatch
Свойства Stopwatch
Elapsed
Свойство Elapsed
позволяет получить общее затраченное время, измеренное текущим экземпляром класса Stopwatch
. Описание свойства выглядит следующим образом:
public TimeSpan Elapsed { get; }
Свойство возвращает объект типа TimeSpan
— интервал времени, используя который, можно получить время выполнения операции в удобном для вас виде. Например,
//получаем объект TimeSpan TimeSpan ts = stopwatch.Elapsed; // Создаем строку, содержащую время выполнения операции. string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine(elapsedTime);
ElapsedMilliseconds
Свойство ElapsedMilliseconds
позволяет получить общее затраченное время, измеренное текущим экземпляром класса Stopwatch
в миллисекундах. В примере использования класса Stopwatch
выше продемонстрировано использование этого свойства.
Elapsed Ticks
Свойство Elapsed
позволяет получить общее время выполнение операции в тактах таймера, измеренное текущим экземпляром Stopwatch
. Такт — это наименьшая единица времени, которую Stopwatch
может измерять таймер. В следующем примере показано использование свойства Elapsed
для измерения времени, затраченного на преобразование строки в целое число типа int
.
int num; //создаем объект Stopwatch stopwatch = new Stopwatch(); //засекаем время начала операции stopwatch.Start(); num = int.Parse("135"); //останавливаем счётчик stopwatch.Stop(); Console.WriteLine($"num = {num}"); //смотрим сколько тактов было затрачено на выполнение Console.WriteLine(stopwatch.ElapsedTicks);
Результатом выполнения этого кода может быть вот такой вывод консоли:
16878
Is Running
Свойство IsRunning
позволяет получить значение типа bool
, указывающее на то запущен ли в данный момент таймер Stopwatch
.
Поля Stopwatch
Класс Stopwatch
содержит два статических поля, позволяющих получить сведения о настройках таймера.
Frequency
Поле Frequency
содержит частоту таймера в виде количества тактов в секунду.
public static readonly long Frequency;
Это поле удобно использовать вместе со свойством Elapsed
для преобразования количества тактов в секунды. Например,
int num; long freq = Stopwatch.Frequency; //частота таймера Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); num = int.Parse("135"); //останавливаем счётчик stopwatch.Stop(); double sec = (double)stopwatch.ElapsedTicks / freq; //переводим такты в секунды Console.WriteLine($"num = {num} \r\n Частота таймера {freq} такт/с \r\n Время в тактах {stopwatch.ElapsedTicks} \r\n Время в секундах {sec}");
Обращу внимание только на то, как происходит перевод тактов в секунды. Учитывая особенности деления целых чисел в C#, для того, чтобы получить конкретное значение секунд нам потребовалось привести одно из значений (в данном случае значение свойства ElapsedTicks
) к типу double
.
Is High Resolution
Свойство Is
указывает, зависит ли таймер Stopwatch
от счетчика производительности высокого разрешения (true
) или же использует класс DateTime
(false
).
public static readonly bool IsHighResolution;
Пример использования поля
class Program { static void Main(string[] args) { DisplayTimerProperties(); } public static void DisplayTimerProperties() { if (Stopwatch.IsHighResolution) { Console.WriteLine("Операции рассчитываются с использованием системного счетчика производительности с высоким разрешением."); } else { Console.WriteLine("Операции рассчитываются с использованием класса DateTime."); } long frequency = Stopwatch.Frequency; Console.WriteLine($" Частота таймера = {frequency}"); long nanosecPerTick = (1000L * 1000L * 1000L) / frequency; Console.WriteLine($" Таймер работает с точностью до {nanosecPerTick} наносекунд"); } }
Вывод консоли будет иметь следующий вид:
Частота таймера = 10000000
Таймер работает с точностью до 100 наносекунд
Методы Stopwatch
Рассмотрим основные методы класса Stopwatch
, которые мы можем использовать для измерения точного времени выполнения операции в C#.
Start и Stop
Метод Start()
запускает или возобновляет работу таймера Stopwatch
. В свою очередь, Stop()
выполняет противоположную операцию — останавливает работу таймера. Использование этих методов продемонстрировано в самом первом примере из этой статьи.
Start New
Метод Start
выполняет сразу несколько операций — он инициализирует новый экземпляр класса Stopwatch
, обнуляет счётчик затраченного времени и запускает таймер. То есть, этот метод позволяет немного сократить исходный код программы. Например, код из первого примера можно было бы записать вот так:
Stopwatch stopwatch = Stopwatch.StartNew();//создаем и запускаем таймер for (int i = 0; i < 10001; i++) { Console.WriteLine(i); } //останавливаем счётчик stopwatch.Stop(); //смотрим сколько миллисекунд было затрачено на выполнение Console.WriteLine(stopwatch.ElapsedMilliseconds);
Reset
Метод Reset()
останавливает измерение интервала времени и обнуляет счётчик затраченного времени. Использование Reset() позволяет избежать создания новых экземпляров Stopwatch
для измерения времени, затраченного на выполнение нескольких операций в C#.
Stopwatch stopwatch = Stopwatch.StartNew();//создаем и запускаем таймер for (int i = 0; i < 100; i++) { Console.WriteLine(i); } //останавливаем счётчик stopwatch.Stop(); //смотрим сколько миллисекунд было затрачено на выполнение Console.WriteLine($"Первая операция {stopwatch.ElapsedMilliseconds}"); stopwatch.Reset(); //сбросили счётчик stopwatch.Start(); //запустили счётчик for (int i = 0; i < 100; i++) { Console.WriteLine(i*i); } stopwatch.Stop(); //смотрим сколько миллисекунд было затрачено на выполнение Console.WriteLine($"Вторая операция {stopwatch.ElapsedMilliseconds}");
Restart
Метод Restart()
останавливает измерение интервала времени, обнуляет затраченное время и повторно запускает таймер. Таким образом, предыдущий пример можно переписать следующим образом:
Stopwatch stopwatch = Stopwatch.StartNew();//создаем и запускаем таймер for (int i = 0; i < 100; i++) { Console.WriteLine(i); } //останавливаем счётчик stopwatch.Stop(); //смотрим сколько миллисекунд было затрачено на выполнение Console.WriteLine($"Первая операция {stopwatch.ElapsedMilliseconds}"); stopwatch.Restart(); //перезапускаем счётчик for (int i = 0; i < 100; i++) { Console.WriteLine(i*i); } stopwatch.Stop(); //смотрим сколько миллисекунд было затрачено на выполнение Console.WriteLine($"Вторая операция {stopwatch.ElapsedMilliseconds}");
Итого
Класс Stopwatch
из пространства имен System.
C# позволяет измерить время выполнения операции с точностью до 100 наносекунд в зависимости от того, что используется для работы с интервалами времени — таймер высокого разрешения или же класс DateTime
.