性能テストを計画実行するときによく起こりがちな問題とその解決策4選

こんにちは。てぃろです。

今回は性能テストの話です。これまで多くの開発に関わってきましたが、どの開発でも最も忘れられがちだったのが性能テストでした。

性能テストと言っても、性能という言葉が意味することは複数あり、

  • レイテンシやレスポンスタイムといった、クライアントサイドから見たもの
  • CPUやメモリなどのリソースの利用量といった、サーバーサイドから見たもの

の2種類に大きく分類できると思います。品質特性で言い換えれば、可用性や資源効率性がここで扱う内容です。

つまり、開発時にこれらを考慮することが現場では少ないというのが私の実感です。そのためか、開発の終盤になっていざ性能テストをしようという段階で非常に大きな問題になることが多かった気がします。

そこで今回は私がよく遭遇してきた性能テストの問題とその解決方法について紹介していきたいと思います。

問題1:性能テストケースでボトルネック調査の観点が抜けている

性能テストを実施するにはテストケースが必要になるのは当然ですが、そのケース作成時に確認すべき観点が不足していることがほとんどです。

性能テストの目的は「要求性能を満たしているかを確認すること」であることは間違いないですが、これは本質的ではありません。性能テストの本質は「要求性能を満たしていない箇所を発見して修正し、要求性能を満たせるようにすること」であるはずです。

この考え方が抜けているせいで、テストケースの確認観点としてボトルネック調査をするためのメトリクス取得が不足してしまいます。

性能テストは1回の実行に非常に大きなコストがかかることが多いですので、要求性能を満たしていないことを発見してメトリクスが足りていないことにそこで気づいたとしたら、その大きなコストのケースを再実行する必要があり、スケジュール遅延は必至です。

この問題を解決する手段は、シンプルにケース作成を周到にすることです。

ケースで使用されるアーキテクチャとその処理内容を十分検討し、どこがボトルネックになりやすいかを予想することで取得するべきメトリクスにあたりを付けていきます。あたりを付けるべき箇所は以下のようなものがあります。

  • 外部提供のAPIやクラウドサービスを利用している場合、その利用量の上限はないか
  • キューを使っている場合、そのスループットの上限はいくつか
  • DB処理が含まれている場合、コネクション数の上限はいくつか
  • 一時でもストレージ保存が含まれている場合、ストレージ容量やストレージへのアクセス速度はどの程度か

多くのケースではこういった観点で見ておけば取得するべきメトリクスやボトルネックになりそうな箇所にあたりがつけられると思います。

ただし、調査のためとはいえログの出し過ぎには要注意です。場合によってはログ出力が性能に影響することがありますので、複数箇所で出すとしても最低限のログ量にしておくように心がけましょう。

問題2:性能テストを実行してはじめてケースの難しさに気づく

上述したように、性能テストはその特性上1回あたりの実行コストが非常に大きいことが多いです。

事前準備をいくら周到にしたところで、実行してみるとうまく想定したとおりのケースを実行できない・・・、ということはかなり多いです。私の実感としては9割のケースで1回目の実行は失敗します。

そうすると、実行コストが大きいので再実行することもスケジュール的に難しいということになってしまいます。

この問題を解決する手段は、お試しケースを用意して早急に実行することです。

問題の本質は、結局のところ「本当にその性能テストケースで用意するべきことがわかっていなかった」ということであり、実行する前の準備ではその準備することそのものが足りていないということなのです。

だったら話は単純で一度そのケースを実行してみればよいのです。ただし、本当に必要なケースを実行しようとすると大量のデータを用意するなどかなり大きなコストになるので問題としては解決していません。

なので、データ量を本来よりかなり小さくしたりして実行コストを極めて低くした状態で1ケース実行すればよいのです。私はこれをお試しケースと呼んでいます。

このお試しケースは、性能テストの実行に必要な要素を見極めることを目的としているので必ずしもログやメトリクス取得の準備をすべて終えておく必要はありません。あるに越したことはないですが、あくまでケースを実行できるように環境を整えることを優先するべきです。

問題3:性能テストの実行期間が短すぎる

ここまで読んでいただいた方はお気づきと思いますが、性能テストというのは1ケース実行するのにコスト、つまり時間が非常に多くかかります。その上、実行そのものを失敗するリスクを秘めているものです。さらに言えば、性能テストで発見されたボトルネックを解消する修正は機能的な修正を行うよりもはるかにコストが大きいことがほとんどです。

こういった現実を知る人が少ないことが多いからか、機能的な観点が重視されているからかわからないですが、性能テストはかなり期間が短いことがほとんどです。

この問題を解決する手段は、当然ですが、性能テスト期間を十分に取ることです。

「それが難しいんだよ!」という声が聞こえてきそうですが、おっしゃるとおりですし、私もそれで苦労してきました。だからこそ、ここまで述べてきたような本来性能テストを実施するには足りていなかったはずの観点を性能テストの期間を十分に取るための見積もり根拠として使ってほしいのです。

具体的に言うと、以下のような形です。

  • 特性の違うケースそれぞれについて、お試しケースを1ケース分用意し、その実行時間とそれによって発見される不備を修正する時間を作る。これによりその後の性能テスト実行をスムーズに行えるようにし、性能テスト実行そのものの失敗リスクを軽減する
  • 性能テストの結果検証のために必要なメトリクスやログはXXX程度必要であるため、性能テストのための環境準備期間が必要である
  • 性能テストは実行だけでなく、結果検証を慎重に行う必要があるため、その期間が必要である
  • 結果を検証した結果、問題が発見されること、また機能テストより複雑な修正になることがほとんどであるため機能テストよりも修正による期間をXX%多くとる

特に4点目については強く主張する必要があります。問題1のところでも書きましたが性能テストの本質は「問題を発見して修正すること」にあります。「修正すること」を計画に入れることが極めて重要ですが、あらゆるテスト計画においてよく無視されてしまっている工程だからです。

このようにして、性能テスト計画で見積もるようにしていけば、性能テスト期間をこれまでより多く確保しやすくなるのではないでしょうか。

問題4:すべてのケースを消化できない

問題3で述べた解決策を講じたとしても、ビジネス要件上期間を延ばせないことは往々にしてあります。それによって結果的にすべてのテストケースを消化しきれないということはあるでしょう。

こうなると、最終手段としてテストケースを削っていくしかありません。

ただむやみに削ってしまっては、本来発見すべきだった性能問題が流出してしまうことになってしまうのでそれが一番良くありません。そのためテストケースは適切に品質リスクを考慮して削っていくことが望ましいです。

当然ですが、一番避けるべきリスクは「サービスが停止してしまうような事象が発生しないか」であり、この問題が発生する可能性のあるケースはかならず残すべきです。

次に考えるべきはレイテンシに関わるケースと思います。特にレイテンシはUXに直結するので非常に重要です。ただ、クライアント側のUXの工夫でレイテンシが多少遅くとも問題ないケースもあります。性能テストでは積極的にそういった「実質UXの観点で問題のないケース」を削っていくことにしましょう。

最後にバッチ処理に関するケースも削れる可能性があります。バッチ処理が遅いほとんどの理由はDBコネクションの枯渇かアプリのロジックの無駄によることだと思います。ただ、クラウド全盛期の現代においてはこれらの問題はインスタンスやDBのスケールアウトもしくはスケールアップをすることで解決することが可能です。そのため、本来はみっちりと原因追求して修正するべきバッチ処理のケースをほとんど削ることができるのです。

ただし、このバッチ処理のケースを削るのは当然諸刃の剣であり、スケールアウトとスケールアップをみやみにやることは大変なインフラコストの増大を意味します。ビジネス要件上のタイミングによってテストできる時間がないのであれば仕方ないとしても一時しのぎでしかないことは間違いありません。後日テストをやり直して修正する計画をセットで考えることは必須です。

さいごに

今回は性能テストを進める上でよく直面する問題とそれに対する解決策を紹介してきました。

ここに挙げた内容はよくあるものであり、解決策もその一部であって状況によっては他の解決策も存在しえます。ただ、考え方の本質は変わることはなく、特にケース削減において品質リスクとして顕在化する可能性が高い問題が何かを見極めるということは共通します。

ただ、このような性能テストを計画し実行するには高度なエンジニアリングの経験が必要になると思います。

UXでカバーできること、ボトルネックになりやすい箇所に気づく勘、使われているインフラの特性やリソースの割当上限の知識など、かなり広範な知識と経験が必要になるのです。これを考えるとほとんどの現場で考えきれないことはある意味仕方のないことと言えるかもしれません。

もっと言えば、開発の入門書などでは性能に関わる品質特性の説明はしていると思いますが、テストを学ぶときには機能テストの観点での話が中心であって性能テストについて学ぶ機会がほとんどないのだと思います。そのため多くの経験がまだ浅いエンジニアは性能テストを開発工程から忘れがちになっているのではないでしょうか。

もはやこれは本人のせいではなく、ソフトウェア開発業界全体でそういう教育をしてしまっているせいなのではないかと思うくらいです。

このような状況だからこそ、性能テストの本質や事情を現場もマネジメント層も理解して計画をしておく必要があり、それが本質的に品質が高いソフトウェアを開発可能とすることになるのだと思います。