Ответ 1
Я отвечу на третью часть вашего вопроса, так как я сделал это с некоторым успехом несколько раз.
как вы примените red- > green- > refactor, когда производительность будет критическое требование?
- Записывайте тесты для фиксации регрессий, для того, что вы планируете изменить, и других методов, которые могут замедляться в результате ваших изменений.
- Запишите тест производительности, который не работает.
- Сделайте улучшения производительности, часто выполняйте все тесты.
- Обновите тесты на пиннинг, чтобы более точно настроить производительность.
Записывать тесты пиннинга
Создайте вспомогательный метод, подобный этому, к тому, что вы хотите вывести.
private TimeSpan Time(Action toTime)
{
var timer = Stopwatch.StartNew();
toTime();
timer.Stop();
return timer.Elapsed;
}
Затем напишите тест, который утверждает, что ваш метод не требует времени:
[Test]
public void FooPerformance_Pin()
{
Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(0));
}
Когда он терпит неудачу (с фактическим временем, прошедшим в сообщении об ошибке), обновите время с чем-то чуть больше фактического времени. Повторите, и это пройдет. Повторите это для других функций, производительность которых может повлиять на ваши изменения, в результате чего-то вроде этого.
[Test]
public void FooPerformance_Pin()
{
Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(0.8));
}
[Test]
public void BarPerformance_Pin()
{
Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(6));
}
Записать неудачный тест производительности
Мне нравится называть этот тест "испытанием на избиение". Это только первый шаг теста пиннинга.
[Test]
public void FooPerformance_Bait()
{
Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(0));
}
Теперь работайте над улучшением производительности. Выполняйте все тесты (пиннинг и травление) после каждого предварительного улучшения. Если вы добьетесь успеха, вы увидите, что время на выходе сбоя теста на изнашивание снижается, и ни один из ваших тестов на пиннинг не завершится.
Когда вы будете удовлетворены улучшениями, обновите тест пиннинга для кода, который вы изменили, и удалите тест на изнашивание.
Что вы будете делать с этими тестами сейчас?
Самое опасное, что нужно сделать, - отметить эти тесты с помощью атрибута Explicit и сохранить их в следующий раз, когда вы хотите проверить производительность.
На противоположной стороне спектра работы создание разумно хорошо контролируемой подсистемы в CI для запуска таких тестов - действительно хороший способ контролировать регрессии производительности. По моему опыту есть много беспокойства о том, что они "случайно не работают из-за загрузки процессора из чего-то другого", чем есть фактические сбои. Успех такого рода усилий зависит в большей степени от командной культуры, чем от вашей способности осуществлять контроль над окружающей средой.