Календарный момент, длительность и измеренное прошедшее время описывают разные величины. DateTime задаёт положение на принятой временной шкале, TimeSpan — знаковый интервал между моментами либо продолжительность, а Stopwatch — результат наблюдения за выполнением программного участка. Момент можно сравнить с моментом, к моменту можно прибавить длительность, а разность двух моментов снова является длительностью.

Числовое представление времени всегда связано с единицей. Компоненты Days, Hours, Minutes и Seconds описывают части TimeSpan, свойства TotalDays, TotalHours и TotalSeconds — полную величину в выбранной единице, а Ticks — дискретное представление с фиксированной шкалой TimeSpan. Такты Stopwatch.ElapsedTicks принадлежат другой шкале и переводятся в секунды через Stopwatch.Frequency; равенство названия Ticks не означает равенства единиц.

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

Опора — Раздел 21: время, длительность и измерение. Дополнительно используются классы роста и инварианты из Раздела 12, массивы, поиск и сортировка из Раздела 15, строки и StringBuilder из Раздела 19, структуры для календарных интервалов и результатов эксперимента из Раздела 20.

Каждая задача оформляется отдельной консольной программой полным шаблоном курса и компилируется с <Nullable>enable</Nullable>. Разрешены только конструкции Разделов 1–21. Календарные значения одной задачи создаются с одинаковым DateTimeKind и интерпретируются в одной заранее принятой временной шкале; часовые пояса, переходы локального времени, календарные системы, DateOnly и TimeOnly не рассматриваются. Замеры выполняются в конфигурации Release без подключённого отладчика; версия .NET, операционная система и основные параметры среды записываются в отчёт. Random, многопоточность, Thread.Sleep, принудительный запуск сборщика мусора, BenchmarkDotNet, обработка исключений и внешние профилировщики запрещены. Подготовка входов, создание копий, вывод и проверка результата находятся вне измеряемого участка, если условие прямо не требует измерить полную стратегию. Каждое вычислительное ядро возвращает либо накапливает наблюдаемую контрольную сумму, а слишком дорогая серия прекращается по заранее установленному пределу.


База практических заданий

Уровень I. Базовый

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

1. Создание, форматирование и сравнение моментов: Создать четыре значения DateTime через конструктор: начало и конец двух работ. Все значения имеют одинаковый DateTimeKind. Через операторы сравнения определить:

  • хронологический порядок;
  • совпадение границ;
  • самый ранний момент;
  • самый поздний момент.

Вывести значения в стабильном формате:

yyyy-MM-dd HH:mm:ss

через InvariantCulture. Отдельно вывести Ticks и Kind. Объяснить, почему календарный момент не является продолжительностью и почему форматированный текст не изменяет само значение.

2. Компоненты, полные величины и такты TimeSpan: Создать длительность:

2 дня 3 часа 40 минут 15 секунд 250 миллисекунд

через сложение результатов TimeSpan.FromDays, FromHours, FromMinutes, FromSeconds и FromMilliseconds. Вывести:

  • Days, Hours, Minutes, Seconds, Milliseconds;
  • TotalDays, TotalHours, TotalMinutes, TotalSeconds;
  • Ticks;
  • результат деления Ticks / TimeSpan.TicksPerSecond.

Подтвердить восстановление длительности через TimeSpan.FromTicks. Объяснить различие между компонентом Hours и полной величиной TotalHours.

3. Арифметика момента и длительности: Даны начало 2026-07-10 22:35:00 и конец 2026-07-12 01:20:15. Получить:

TimeSpan duration = end - start;

Затем проверить:

start + duration == end
end - duration == start

Создать отрицательную длительность start - end, сравнить её с TimeSpan.Zero и вывести полное число секунд. Объяснить, почему знак разности зависит от порядка операндов.

4. Последовательность этапов: Работа начинается в заданный момент и состоит из трёх этапов: подготовка, вычисление и передача результата. Длительности создаются через TimeSpan.FromMinutes и TimeSpan.FromSeconds. Вычислить:

  • начало и конец каждого этапа;
  • общую длительность;
  • окончание всей работы;
  • восстановленное начало через вычитание общей длительности.

Подтвердить, что сумма трёх этапов равна разности общего конца и начала.

5. Полуоткрытые интервалы: Даны два непустых интервала [start, end) с start < end. По заданной системе ветвей различить:

  1. первый расположен строго раньше второго;
  2. второй расположен строго раньше первого;
  3. интервалы касаются границами;
  4. интервалы пересекаются на положительной длительности.

При пересечении вычислить:

intersectionStart=max(start1,start2),intersectionStart=\max(start_1,start_2), intersectionEnd=min(end1,end2).intersectionEnd=\min(end_1,end_2).

Подтвердить intersectionStart < intersectionEnd. Объяснить, почему общий граничный момент не принадлежит обоим полуоткрытым интервалам одновременно.

6. Периодические контрольные точки: Даны начальный момент, положительный шаг TimeSpan и число точек count >= 0. Построить DateTime[]:

ti=t0+iΔt.t_i=t_0+i\Delta t.

Текущий момент обновлять прибавлением шага. Предусловие гарантирует представимость всех результатов и произведения step.Ticks * (count - 1). Для непустого результата проверить последнюю точку независимой формулой. Инвариант: перед итерацией i текущий момент равен t_i, а префикс [0, i) уже заполнен правильными значениями.

7. Агрегирование длительностей: Дан непустой TimeSpan[] stages. Вычислить:

  • сумму через TimeSpan.Zero;
  • минимум;
  • максимум;
  • среднюю длительность через целочисленное среднее тактов;
  • число отрицательных, нулевых и положительных длительностей.

Вывести результаты в полных секундах и компонентах. Указать, что деление суммарного числа тактов может отбросить остаток меньше одного такта.

8. Снимок текущего момента: Один раз получить:

DateTime captured = DateTime.Now;

На основе только этого значения вычислить срок через 90 минут и сформировать все строки одного отчёта. Затем получить второй текущий момент и сравнить его с captured. Объяснить, почему несколько независимых вызовов DateTime.Now не образуют один согласованный снимок и почему фактический текущий момент нельзя использовать как фиксированный ожидаемый результат теста.

9. Жизненный цикл Stopwatch: Создать Stopwatch и последовательно исследовать:

  1. состояние после создания;
  2. Start;
  3. выполнение заданного цикла;
  4. Stop;
  5. повторный Start без сброса;
  6. второй одинаковый участок;
  7. Stop;
  8. Reset;
  9. Restart;
  10. третью работу и окончательный Stop.

После каждого этапа вывести IsRunning, ElapsedTicks и Elapsed. Объяснить накопление после повторного Start, различие Reset и Restart и невозможность считать показание до остановки автоматически окончательным.

10. Единицы Stopwatch: Для одного вычислительного участка сохранить:

long counterTicks = stopwatch.ElapsedTicks;
TimeSpan elapsed = stopwatch.Elapsed;

Вычислить секунды двумя согласованными способами:

seconds1=counterTicksStopwatch.Frequency,seconds_1= \frac{counterTicks}{Stopwatch.Frequency}, seconds2=elapsed.TotalSeconds.seconds_2=elapsed.TotalSeconds.

Сравнить значения с разумным допуском и отдельно вывести TimeSpan.TicksPerSecond и Stopwatch.Frequency. Не использовать TimeSpan.FromTicks(counterTicks). Объяснить, почему такты счётчика и такты TimeSpan нельзя считать одной единицей без проверки шкалы.

11. Изоляция измеряемого участка: До запуска таймера построить отсортированный массив из 100_000 целых и массив фиксированных запросов. Между Start и Stop выполнять только многократный линейный поиск. Подготовка входов, печать и проверка индексов выполняются снаружи. Внутри измерения накапливается контрольная сумма найденных индексов; она выводится после остановки и сверяется с заранее вычисленным ожидаемым результатом.

12. Заданная серия по размерам: Для метода суммы массива использовать размеры:

2^10, 2^12, 2^14, 2^16, 2^18, 2^20

Для каждого размера:

  1. создать детерминированный массив вне таймера;
  2. выполнить три прогревочных вызова;
  3. провести 15 измеряемых повторов;
  4. перед повтором вызвать Restart, после ядра — Stop;
  5. сохранить ElapsedTicks;
  6. вычислить минимум, максимум, среднее и размах;
  7. вывести среднее число тактов на элемент;
  8. проверить одинаковую сумму всех повторов.

Протокол задан полностью; требуется только точная реализация и объяснение ожидаемого линейного роста числа операций.


Уровень II. Продвинутый

Условие задаёт календарную систему либо исследовательский вопрос, но не готовое представление интервалов, число проходов, измеряемую границу и способ агрегации повторов. Требуется самостоятельно спроектировать расписание или эксперимент, обеспечить представимость дат, одинаковость входов и воспроизводимость состояния и связать временные данные с числом операций. В отличие от Уровня I ученик определяет сам протокол и достаточное состояние решения.

1. Хронология контрольных событий: Дан неупорядоченный DateTime[] с возможными повторами. Построить упорядоченную независимую копию и определить:

  • самый ранний и поздний моменты;
  • полную продолжительность наблюдения;
  • число пар соседних совпадающих моментов;
  • все положительные промежутки между соседними различными событиями;
  • минимальный, максимальный и средний положительный промежуток.

Если положительных промежутков нет, вернуть отдельный статус. Исходный массив сохраняется.

2. Объединение занятых интервалов: Объявить:

public struct TimeInterval
{
    public DateTime Start;
    public DateTime End;
}

Инвариант:

Start<End.Start<End.

Для массива корректных полуоткрытых интервалов:

  1. создать независимую копию;
  2. устойчиво отсортировать её по Start, затем по End;
  3. слить пересекающиеся и соприкасающиеся интервалы;
  4. сначала использовать буфер максимальной длины с логическим размером;
  5. затем вернуть массив точного размера.

Вычислить суммарную занятую длительность и массив свободных промежутков между объединёнными интервалами.

3. Периодическое расписание с запретами: Даны начало, конец, положительный шаг и массив корректных запрещённых полуоткрытых интервалов. Сформировать все моменты:

start+kstep,start+k\cdot step,

которые строго меньше end и не принадлежат ни одному запрету. Число результата неизвестно заранее, поэтому организовать два прохода: подсчёт и заполнение. Вычисление следующего момента должно завершаться до выхода за допустимый диапазон DateTime. Доказать завершимость через положительность шага и строгое продвижение момента.

4. Пиковая одновременность: Дан массив непустых полуоткрытых интервалов. Для каждого создать два события:

  • начало: +1;
  • конец: -1.

Устойчиво отсортировать события по моменту, а при равенстве обработать завершения раньше начал. Последовательным проходом определить:

  • максимальное число активных интервалов;
  • первый момент достижения максимума;
  • все полуоткрытые участки, на которых сохранялся максимум.

Обосновать порядок событий на общей границе.

5. Безопасный календарный сдвиг: Спроектировать:

static bool TryShift(
    DateTime moment,
    TimeSpan delta,
    out DateTime result)

Обработка исключений запрещена. До вызова AddTicks проверить, что сумма:

moment.Ticks+delta.Ticksmoment.Ticks+delta.Ticks

лежит между DateTime.MinValue.Ticks и DateTime.MaxValue.Ticks. Для проверки разрешено временно использовать decimal, чтобы сложение двух long не переполнилось. При отказе вернуть false и default; при успехе сохранить DateTimeKind исходного момента. Проверить сдвиги около обеих границ диапазона.

6. Сводка серии измерений: Спроектировать:

public struct TimingSummary
{
    public int InputSize;
    public int Repetitions;
    public long MinimumTicks;
    public double MedianTicks;
    public long MaximumTicks;
    public double MeanTicks;
    public double RelativeRange;
}

Метод анализа:

  • не изменяет исходный массив;
  • создаёт копию для сортировки;
  • поддерживает нечётное и чётное число повторов;
  • вычисляет медиану;
  • определяет относительный размах как (max - min) / mean;
  • возвращает отдельный статус, если серия пуста либо среднее равно нулю.

Автоматически удалять «выбросы» запрещено: большой разброс является результатом эксперимента.

7. Линейный и бинарный поиск: Для размеров:

n=210,212,,220n=2^{10},2^{12},\ldots,2^{20}

построить одинаковые отсортированные массивы и фиксированный набор присутствующих и отсутствующих запросов без Random. Реализовать оба поиска со счётчиками сравнений. Самостоятельно определить прогрев, число повторов, порядок чередования и контрольную сумму. Сопоставить:

  • среднее число сравнений;
  • медиану времени;
  • разброс;
  • классы O(n)O(n) и O(logn)O(\log n).

8. Сортировка вставками и Array.Sort: Для нескольких размеров подготовить три детерминированные формы входа:

  • упорядоченную;
  • обратную;
  • пилообразную.

Перед каждым повтором вне таймера создавать одинаковые копии исходного массива. Измерять только сортировку; после остановки проверять упорядоченность и совпадение результатов. Для сортировки вставками считать сравнения и перемещения и сопоставить лучший и худший случаи с O(n)O(n) и O(n2)O(n^2). Array.Sort рассматривать как O(nlogn)O(n\log n) по контракту курса.

9. Конкатенация и StringBuilder: Для возрастающих n построить строку из n одинаковых символов:

  1. повторной конкатенацией;
  2. через StringBuilder с начальной ёмкостью n.

Размеры выбираются заранее; серия прекращается, если одна стратегия превышает установленный предел длительности. Выполнить прогрев, чередовать порядок стратегий, измерять только построение и проверять равенство строк. Сопоставить наблюдения с суммой длин копируемых префиксов:

0+1++(n1)=n(n1)2.0+1+\dots+(n-1) = \frac{n(n-1)}{2}.

10. Пять классов роста: Реализовать пять вычислительных ядер с наблюдаемой контрольной суммой:

  1. постоянное число действий;
  2. один проход длины n;
  3. последовательное деление состояния на 2;
  4. двойной проход n × n;
  5. внешний проход 1..n с внутренним делением текущего индекса на 2.

Для нескольких размеров:

  • посчитать точное число основных операций;
  • провести серии измерений;
  • выбрать отдельный безопасный диапазон для квадратичного ядра;
  • классифицировать ядра как O(1)O(1), O(n)O(n), O(logn)O(\log n), O(n2)O(n^2) и O(nlogn)O(n\log n);
  • объяснить случаи, в которых время малых размеров ещё не отражает класс роста.

11. Честный протокол для изменяющего алгоритма: Исследовать сортировку вставками в серии повторов двумя способами:

  1. ошибочно сортировать один и тот же массив повторно;
  2. перед каждым измерением восстанавливать одинаковый исходный порядок вне таймера.

До запуска предсказать число сравнений первого и последующих повторов ошибочной серии. Затем спроектировать корректный протокол, в котором подготовка копии не входит в измеряемое ядро, но учитывается отдельной контрольной серией. Объяснить загрязнение входа предыдущим повтором.

12. Цена предварительной сортировки: Сравнить две полные стратегии обработки неизменяемого массива длины n:

  1. выполнить q линейных поисков;
  2. создать копию, отсортировать её и выполнить q бинарных поисков.

Для каждого (n, q) обе стратегии получают одинаковый набор запросов. Во второй стратегии измеряются копирование, сортировка и поиски вместе. Построить серии для нескольких n и q, определить наблюдаемый диапазон окупаемости и сопоставить:

Tlinear=O(qn),T_{\mathrm{linear}}=O(qn), Tsorted=O(nlogn+qlogn).T_{\mathrm{sorted}} = O(n\log n+q\log n).

Отдельно сравнить с результатами II.7, где предварительная обработка не входила в поисковое ядро.


Уровень III. Экспертный

Исследуется не прикладное расписание и не само время алгоритма, а достоверность измерительного вывода. До запуска требуется записать гипотезу, единицу наблюдения, измеряемую границу, ожидаемое число операций, возможные искажения и критерий принятия вывода; после — разделить устойчивое наблюдение, шум, ошибку протокола и утверждения, которые данные не подтверждают.

1. Календарные часы и монотонный измеритель: Один короткий вычислительный участок измерить многократно:

  • разностью двух последовательных DateTime.Now;
  • отдельным Stopwatch.

Для каждого способа подсчитать:

  • число нулевых результатов;
  • число отрицательных результатов;
  • минимум положительного значения;
  • число различных наблюдавшихся значений.

Затем повторить опыт, объединяя в один замер 1, 10, 100 и 1000 выполнений ядра. Объяснить назначение настенных календарных часов, монотонного счётчика, дискретность наблюдения и необходимость пакетирования слишком короткой работы.

2. Такты двух разных шкал: Получить Stopwatch.ElapsedTicks, Stopwatch.Frequency, Stopwatch.Elapsed.Ticks и TimeSpan.TicksPerSecond. До запуска предсказать, какие отношения обязаны выполняться, а какие зависят от платформы. Вычислить длительность в секундах:

  1. через ElapsedTicks / Frequency;
  2. через Elapsed.TotalSeconds.

Затем намеренно интерпретировать ElapsedTicks через TimeSpan.FromTicks и показать расхождение, если частоты различаются. Сформулировать общий вывод: числовое значение без единицы и шкалы неполно.

3. Прогрев и порядок сравнения: Сравнить два алгоритма на одинаковых входах четырьмя протоколами:

  1. без прогрева в фиксированном порядке A → B;
  2. с прогревом в том же порядке;
  3. с чередованием A → B и B → A;
  4. отдельными сериями.

До запуска перечислить возможные искажения первого вызова и постоянного порядка. После сравнить медианы и разбросы и объяснить, почему совпадение одного протокола с гипотезой не делает его универсально истинным.

4. Загрязнение изменяемого входа: Для сортировки, разворота массива и удаления повторов на месте построить намеренно ошибочные серии, в которых каждый повтор получает результат предыдущего. До запуска проследить состояние входа и число операций хотя бы для первых трёх повторов. Затем исправить протокол двумя способами:

  • восстанавливать копию вне таймера и измерять ядро;
  • измерять полную операцию «копия + ядро».

Показать, что оба исправленных протокола корректны, но отвечают на разные исследовательские вопросы.

5. Зависимость от расположения данных: Для линейного поиска использовать цель:

  • в первой позиции;
  • в средней позиции;
  • в последней позиции;
  • отсутствующую.

Для сортировки вставками использовать упорядоченный, обратный и пилообразный массив. До запуска вывести точное либо асимптотическое число сравнений и перемещений. После объяснить, почему размер входа не определяет единственную длительность, а обозначение O(n)O(n) или O(n2)O(n^2) требует уточнения рассматриваемого случая.

6. Накладные расходы и пакетирование: Отдельными сериями измерить:

  • пустой участок между Start и Stop;
  • одну простую арифметическую операцию;
  • пакеты из 10, 10^2, 10^3 и 10^4 одинаковых операций.

Для каждого пакета вычислить медиану и условное число тактов на операцию. Базовую серию вывести рядом, но не вычитать как точную поправку. Объяснить, при каких размерах накладные расходы и шум сравнимы с полезной работой и почему нестабильная либо отрицательная оценка после простого вычитания не доказывает отрицательное время операции.

7. Аудит ошибочных измерений: Для каждого протокола найти не менее двух дефектов и предложить исправление:

  1. один запуск в Debug под отладчиком;
  2. вывод каждой итерации внутри таймера;
  3. разные входы для сравниваемых алгоритмов;
  4. повторная сортировка одного массива;
  5. сравнение средних без публикации разброса;
  6. перевод ElapsedTicks через TimeSpan.FromTicks;
  7. объявление более низкого времени доказательством лучшей асимптотики на одном размере;
  8. удаление всех медленных повторов без заранее заданного правила.

Для каждого случая указать, какой именно вывод остаётся допустимым после исправления, а не только переписать код.

8. Полный протокол проверки роста: Выбрать три ранее реализованных алгоритма с ожидаемыми классами:

O(n),O(nlogn),O(n2).O(n),\qquad O(n\log n),\qquad O(n^2).

До эксперимента зафиксировать:

  • конфигурацию;
  • версию среды;
  • детерминированные входы;
  • не менее шести размеров;
  • прогрев;
  • 21 измеряемый повтор;
  • порядок сравнения;
  • измеряемую границу;
  • контроль правильности;
  • критерий прекращения слишком дорогой серии.

Для каждого размера сохранить медиану и размах и вычислить:

tn,tnlog2n,tn2.\frac{t}{n}, \qquad \frac{t}{n\log_2 n}, \qquad \frac{t}{n^2}.

Определить, какая нормировка стабилизируется лучше. Итог разделить на три части: подтверждённое наблюдение в измеренном диапазоне, обнаруженные отклонения и утверждения, которые нельзя переносить на другие размеры, платформы и реализации.


Обязательные контрольные наборы

ЗадачаИсходные данные
I.12028-02-29 23:45:30, 2028-03-01 00:00:00, 2028-03-01 08:15:00, повтор одной границы
I.2длительность из условия
I.3начало 2026-07-10 22:35:00, конец 2026-07-12 01:20:15
I.4начало 2026-07-10 09:30:00; этапы 25 мин, 80 мин, 150 с
I.5раздельные, касающиеся, частично пересекающиеся и вложенные интервалы
I.6начало 2026-01-01 08:00:00, шаг 00:17:30, count = 0,1,5,20
I.700:00:30, 01:15:00, 2.12:00:00, -00:05:00, 00:00:00
I.8один запуск программы с текущим моментом среды
I.9три одинаковых цикла по 10_000_000 итераций
I.10вычислительное ядро не короче нескольких тысяч итераций
I.11длина массива 100_000, запросы [0,50_000,99_999,-1,100_001]
I.12размеры и 15 повторов из условия
II.1события с повторами и переходом через полночь
II.2пять интервалов: раздельные, касающиеся, пересекающиеся и вложенный
II.3окно 08:00–18:00, шаг 15 мин, два запрещённых интервала
II.4[09:00,10:00), [09:30,11:00), [10:00,10:30), [11:00,12:00)
II.5DateTime.MinValue, DateTime.MaxValue и сдвиги -1, 0, 1 такт и ±1 день
II.6[10,11,9,12,100], [5,5,5,5], [4,8,6,10], пустая серия
II.7размеры 2^102^20; цели в начале, середине, конце и вне массива
II.8размеры 128, 512, 2048, 8192; три формы входа
II.9n = 10^2,10^3,5·10^3,10^4,2·10^4 с заранее заданным пределом серии
II.10n = 16,64,256,1024,4096 с отдельным диапазоном квадратичного ядра
II.11обратный массив длины 2048; не менее 15 повторов
II.12n = 10^3,10^4,10^5, q = 1,10,10^2,10^3,10^4
III.1пакеты 1, 10, 100, 1000; не менее 101 повтора
III.2один участок длительностью, достаточной для ненулевого ElapsedTicks
III.3линейный и бинарный поиск либо две сортировки на идентичных копиях
III.4сортировка, разворот и уплотнение на месте
III.5размеры 32, 128, 512, 2048; все расположения и формы из условия
III.6пакеты 1, 10, 10^2, 10^3, 10^4; не менее 31 повтора
III.7все восемь ошибочных протоколов
III.8не менее шести возрастающих размеров и 21 повтор для каждого алгоритма

Итог модуля

Ученик различает календарный момент, знаковую длительность и монотонно измеренное прошедшее время, создаёт и сравнивает DateTime, выполняет арифметику через TimeSpan, строит полуоткрытые интервалы, расписания и системы одновременности и проверяет представимость календарного сдвига. Он управляет полным жизненным циклом Stopwatch, различает такты счётчика и TimeSpan, изолирует вычислительное ядро и проектирует серии с прогревом, одинаковыми входами, восстановлением изменяемого состояния, контрольной суммой, медианой и разбросом. Наблюдаемое время сопоставляется с точным числом операций и классами роста только в пределах зафиксированной конфигурации, размеров и протокола, а ошибочные измерительные выводы распознаются по нарушению единицы, границы эксперимента, состояния входа или правил сравнения.

Покрытие опоры и границы

  • Создание, форматирование и сравнение DateTime: I.1, I.3–I.6, II.1–II.5.
  • TimeSpan, компоненты, полные величины, Ticks и TimeSpan.Zero: I.2–I.7, II.1–II.5.
  • Текущий момент и согласованный снимок: I.8, III.1.
  • Полуоткрытые интервалы, объединение, запреты и одновременность: I.5, II.2–II.4.
  • Представимость календарной арифметики: I.6, II.3, II.5.
  • Stopwatch, Start, Stop, Reset, Restart, Elapsed и IsRunning: I.9–I.12.
  • ElapsedTicks, Stopwatch.Frequency и отличие от тактов TimeSpan: I.10, III.2.
  • Изоляция измеряемого участка и наблюдаемая контрольная сумма: I.11–I.12, II.7–II.12.
  • Прогрев, серия повторов, одинаковые входы и чередование порядка: I.12, II.7–II.12, III.3–III.4.
  • Минимум, медиана, среднее, максимум и разброс: I.12, II.6–II.12, III.1–III.8.
  • Изменяемые входы и восстановление состояния: II.8, II.11, III.4.
  • Ядро против полной стратегии: II.11–II.12, III.4.
  • Зависимость стоимости от формы и расположения входа: II.8, III.5.
  • Постоянные затраты, разрешение таймера и пакетирование: III.1–III.2, III.6.
  • Классы O(1)O(1), O(logn)O(\log n), O(n)O(n), O(nlogn)O(n\log n) и O(n2)O(n^2): I.12, II.7–II.12, III.5 и III.8.
  • Аудит протокола и границы подтверждённого вывода: III.3–III.8.

За границей: часовые пояса, переходы летнего времени, DateTimeOffset, DateOnly, TimeOnly, расширенные календарные правила и платформенные политики преобразования времени относятся к последующим курсам. Высокоточные микроизмерения, аппаратные счётчики, профилировщики, BenchmarkDotNet, статистическое моделирование шума, многопоточность и анализ пауз сборщика мусора также не входят в модуль. Stopwatch позволяет наблюдать длительность в текущей среде, но не доказывает универсальную скорость алгоритма и не заменяет доказательство корректности и асимптотическую оценку.