Руководство по Бенчмарку в .NET. Окончание
Начало
Продолжение
Настройка и очистка
Иногда нужно написать какую-то логику, которая должна выполняться до или после бенчмарка, но мы не хотим, чтобы она участвовала в бенчмарке.
- Метод, помеченный атрибутом
[GlobalSetup], будет выполняться только один раз для тестируемого метода после инициализации параметров бенчмарка и до всех вызовов тестового метода.- Метод, помеченный атрибутом
[GlobalCleanup], будет выполняться только один раз для тестируемого метода после всех вызовов тестового метода.- Метод, помеченный атрибутом
[IterationSetup], будет выполняться ровно один раз перед каждым вызовом теста. Не рекомендуется использовать его в микробенчмарках, так как это может испортить результаты. Однако, он может быть полезен, если тест занимает не менее 100 мс, и вы хотите подготовить некоторые данные перед каждым вызовом.- Метод, отмеченный атрибутом
[IterationCleanup], будет выполняться ровно один раз после каждого вызова. Этот атрибут также не рекомендуется использовать в микробенчмарках.Валидация
Итак, бенчмарк позволяет сравнить между собой производительность методов, которые, по идее, должны делать одно и то же. Однако, если внимательно присмотреться к коду из первой части, можно заметить, что это не так. Метод StringBuilder() выводит лишнюю запятую в конце, в отличие от метода StringJoin(). Эта конкретная ошибка вряд ли сильно повлияла на результаты бенчмарка, но нам может и не повезти с этим в следующий раз.
Хотелось бы иметь какой-то автоматизированный тест, подтверждающий, что результат работы методов одинаковый.
BenchmarkDotNet умеет и это. Всё, что нам нужно сделать, это добавить
ReturnValueValidator в наш тестовый класс, и все готово.[ReturnValueValidator(failOnError: true)]Теперь при попытке запуска нашего бенчмарка, если методы не возвращают одинаковый результат, мы получим ошибку:
public class Benchmarks
{
// остальной код скрыт для краткости
// см. предыдущий пост
}
// Validating benchmarks (Проверка бенчмарков):
Inconsistent benchmark return values in Benchmarks (Несогласованные возвращаемые значения в бенчмарках): StringJoin: 0, 1, 2, 3, 4, StringBuilder: 0, 1, 2, 3, 4,
* Здесь значения кажутся одинаковыми, но на самом деле это из-за того, что BenchmarkDotNet ставит запятую в сообщении об ошибке после результата первого метода. На самом деле это следует читать как:
StringJoin: "0, 1, 2, 3, 4", StringBuilder: "0, 1, 2, 3, 4,"
И бенчмарки не выполнятся. Нам нужно исправить ошибку и убедиться, что результаты обоих методов одинаковы.
Также существует
BaselineValidator, который проверяет, что параметр Baseline=true атрибута Benchmark добавлен только в одном методе. Этот валидатор обязательный.JitOptimizationsValidator проверяет, все ли зависимости проекта оптимизированы. По умолчанию отключен.ExecutionValidator проверяет, могут ли исполниться все бенчмарки, исполняя все методы по одному разу перед запуском тестов. Если в каком-то из методов возникает ошибка, бенчмарки не запускаются. По умолчанию отключен.Источники:
- https://blog.nimblepros.com/blogs/validating-benchmarks/
- https://benchmarkdotnet.org/articles/features/setup-and-cleanup.html
- https://benchmarkdotnet.org/articles/configs/validators.html