私はこれを何度か成功させてきたので、あなたの質問の3番目の部分に答えるつもりです。
パフォーマンスが重要な要件である場合、赤->緑->リファクタリングをどのように適用しますか?
- 変更する予定の内容や、変更の結果として速度が低下する可能性のあるその他の方法について、リグレッションをキャッチするためのピン留めテストを作成します。
- 失敗するパフォーマンステストを作成します。
- すべてのテストを頻繁に実行して、パフォーマンスを向上させます。
- 固定テストを更新して、パフォーマンスをより厳密に固定します。
固定テストを作成する
このようなヘルパーメソッドを作成して、ピン留めしたいものの時間を計ります。
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.Bar()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(6));
}
失敗したパフォーマンステストを書く
私はこの種のテストを「ベイティングテスト」と呼んでいます。これは、ピン留めテストの最初のステップにすぎません。
[Test]
public void FooPerformance_Bait()
{
Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(0));
}
次に、パフォーマンスの向上に取り組みます。暫定的な改善を行うたびに、すべてのテスト(ピン留めとベイト)を実行します。成功すると、ベイティングテストの失敗出力で時間が減少し、ピン留めテストが失敗することはありません。
改善に満足したら、変更したコードのピン留めテストを更新し、ベイティングテストを削除します。
あなたは今これらのテストで何をしますか?
最も気になることは、これらのテストにExplicit属性のマークを付けて、次にパフォーマンスをチェックするときのためにそれらを保持することです。
作業範囲の反対側では、これらの種類のテストを実行するためにCIで適切に制御されたサブシステムを作成することは、パフォーマンスの低下を監視するための非常に優れた方法です。私の経験では、実際の障害よりも「他の何かからのCPU負荷が原因でランダムに障害が発生する」という心配がたくさんあります。この種の取り組みの成功は、環境を管理する能力よりもチームの文化に依存します。