見出し画像

アプリケーション開発時に性能問題はどの時点で考慮すべきか

はじめに

こんにちは。株式会社SHIFT 技術統括部の力石です。主にお客さまのアプリケーション開発プロジェクトで、性能改善、品質向上などの非機能関連のコンサルティングをしています。

アプリケーション開発において性能問題で苦労したことがあるプロジェクト管理者の方は多いと思います。多くのプロジェクトでは、性能に関連する作業は総合テスト工程でおこなうことが多いのではないでしょうか? その場合、チューニングやパラメータ設定だけで性能問題が解決すれば問題ありませんが、設計などに遡って対応せざるを得ないケースがあります。

プロジェクトの規模が大きくなればなるほど、性能に関する難易度は高くなり、また前工程へ遡ることで影響範囲が大きくなり、スケジュールや工数不足に悩むことになります。 私がテスト工程から参加したいくつかの数100億円規模のプロジェクトで、このような性能問題が発生しました。 そのときの教訓をお話しします。

1.総合テストで性能問題が見つかったときの対応

総合テストをおこなっているということは、機能的な不具合は既に解消しているはずです。この時点で発生した性能問題の対応で工程を遡らずにできるのは、開発したアプリケーションやミドルウェアのパラメータチューニングや、 データベースに関連したところでは、インデックスの追加やSQL文へのヒントの追加程度です。この程度の対応で性能問題が解決すればよいのですが、そうならないことがありました。

2.どの工程から性能について検討するか

性能試験をする際に、本番相当のデータ量を用意するという鉄則があります。単体テスト時からそのような環境を用意できるのが理想ですが、実際には総合テストまで準備出来ないことがほとんどではないでしょうか?

実際に動かして処理時間などを計測するのは総合テストでおこなうとしても、それ以前の工程で出来ることもあります。上流工程で対応すると出戻りが無くなり工数の削減になります。

システム構築全体を見ればよいことばかりですが、上流工程で実施することが増えスケジュールが遅延する可能性はあります。今まで上流工程で性能について検討していないのであれば、性能関連の工数や期間をあらかじめ計画しておきましょう。

3.性能解決方法と対応工程

実際にどのようなことをすればよいか例をあげます。性能問題で苦労したことがある人ならば納得していただけると思います。

3.1 パラメータチューニング

  • 解決方法

    • ミドルウェアやOSのパラメータチューニング

  • 対応すべき工程

    • 設計、総合テスト

  • 実施内容

    • 商用相当のデータと負荷量でテストを実施し、パラメータを変更して性能改善します。

本番相当のデータを使用しないと見つけられない問題ですので、総合テストでないと見つけられません。設計工程でパラメータ設計をする際は、各パラメータにどのような値が設定可能か、値を変えた場合に振る舞いがどのように変わるか想定するところまで実施し、総合テストでそれを決定するという流れになります。

3.2 SQL文のヒント

  • 解決方法

    • SQL文へのヒント

  • 対応すべき工程

    • 総合テスト

  • 実施内容

    • 商用相当のデータを使用し、性能問題があるSQL文を洗い出します。
      ヒントを指定することで実行計画を変更し性能改善をします。

これまでの工程で発生せず、本番相当のデータを使用して始めて見つかったのであれば、SQL文へのヒントで対するのも1つの方法です。出来ればSQL文の修正で対応した方が望ましいですが、総合テスト工程でアプリ修正をした場合、多くのテストが必要となるため総合的に判断しヒントで対応することもあるでしょう。

3.3 ロジック修正

  • 解決方法

    • アプリケーションロジックの見直し

  • 対応すべき工程

    • 方式設計

  • 実施内容

    • 各処理で共通して使用しているロジックの場合、処理速度の要件を満たすか確認します。
      例えば、バッチ処理で1時間に100万件の処理が必要としましょう。データを1件毎取り出して処理をするロジックの場合、1秒間に約280件処理が必要です。単純に取り出したデータをファイルに出力し、処理したことをデータベースに更新するだけであれば性能を満足することはできるかもしれません。しかし実際の処理では取り出したデータを元にいろいろな処理が必要になることが多いでしょう。その場合1秒間に280件も処理をするのは難しくなるでしょう。

    • 対応方法として次の案が思いつきます

      • 案1:処理を多重化をする

      • 案2:中間テーブルに必要なデータを抜き出し、その中間テーブルに対して処理を1回のUPDATE文で複数レコードに対して実行する

マシンリソースが潤沢にあれば案1は有力な候補です。処理の途中経過を1件毎ログに出す必要がない場合案2は有力な候補です。
各案のメリット/デメリットを見極めて決定する必要があります。

このような対応が必要なことが総合テスト工程で見つかった場合の対応工数は、方式設計工程で対応するのに比べると何10倍も違ってくるでしょう。

3.4 パッケージソフトの使用方法見直し

  • 解決方法

    • パッケージソフトの使用方法見直し

  • 対応すべき工程

    • 方式設計

  • 実施内容

    • パッケージソフトの使い方についてテンプレートを作成します。
      その内容を元に各開発者は作成します。

使い慣れていないパッケージの場合、パッケージが想定した使い方をしていないために性能が出ないということがあります。

開発者が作りながら勉強していくというプロジェクトは多いのではないでしょうか?その場合いくつかの機能を作った時点でより性能が出る方法が見つかったなら、既に作った物の改善は諦めるか工数をかけて改善することになるでしょう。そうならないためにも設計や開発をする前に先行してパッケージソフトの使用方法のルールを作成する専任のチームを立ち上げるべきです。

3.5 画面設計変更

  • 解決方法

    • 検索条件に制限をかける

  • 対応すべき工程

    • 要件定義

  • 実施内容

    • 要件において技術的に困難な点を洗い出し、依頼元と要件の調整をします。

画面のすべての項目が制限なく検索条件に指定できるようにしたいという要件を見たことはないでしょうか?性能的な問題はデータベースからのデータ取得に時間がかかるのが原因とします。データ件数が少なければ性能問題は発生しませんが、データ件数が多くまたテーブルが正規化され複数に分かれている場合の解決方法は簡単ではありません。

技術的な解決方法として、サマリテーブルの作成や、非正規化などを検討します。それでも要件を満たせない場合は、要件変更をしましょう。マシンリソースの追加や開発工数を追加すれば解決できるかもしれませんが、依頼元もそれよりも要件整理してお金をかけないことを望んでいることも多いでしょう。

検索条件であれば、検索パターンをいくつかに固定する、必須条件を指定する、処理性能に優先順位を付けます。このようなことを依頼元より取り付けるだけで開発はずいぶん楽になるはずです。

3.6 インデックス追加

  • 解決方法

    • データベースにインデックスの追加

  • 対応すべき工程

    • 設計

  • 実施内容

    • 性能のために必要なインデックスを追加します。

    • 他のインデックスも参照し、統合できないか検討します。

インデックスはどの時点で決めていますか?
設計時にどのようなインデックスがあれば性能問題が起きないか考えていますか?必要なインデックスを貼れば検索は速くなりますが、インデックスが多いとINSERT,UPDATE,DELETEの処理が遅くなります。必要なインデックスの情報はデータベース設計者に集め、データベース設計者が各処理で最適になるインデックスを決めていくのが効率よくインデックスの決定が出来ます。

3.7 SQL文修正

  • 解決方法

    • インデックスが使われるようにSQL文を修正

  • 対応すべき工程

    • 開発規約決定、コーディング

  • 実施内容

    • インデックスが有効に使われるようにSQL文をコーディングします。

インデックスを作成してもSQL文がインデックスが使われない書き方になっていたら意味がありません。SQLに詳しくない人にもわかるようにルール化しましょう。またルールに書かれていないパターンでも性能的に怪しそうだと思ったらすぐに相談しましょう。

機能の不具合は単体テストでも気付けますが、性能問題に気付くのは難しいです。コードを書いた人が怪しいと思ったことをその場で解決していけば、その後の工数削減やスキルアップにもつながります。

3.8 ロジック修正

  • 解決方法

    • メモリ効率を考えたアプリケーションロジックの見直し

  • 対応すべき工程

    • 設計、コーディング

  • 実施内容

    • 内部でどのように動くかを考慮し、無駄な処理をしていないかを検討し、改善をしていきます。

メモリ効率を考えた設計をおこなっていますか?
最近のシステムはメモリも潤沢にあり、そんなことを考えなくても性能問題は発生しないことが多くなりました。 それでも大規模システムで扱うデータ量が多くなった場合は気をつける必要があります。無駄にメモリを使うロジックになっていないかを考えてみましょう。

例えば、データベースから読み取ったデータをファイルに出力する処理で、データベースから読み取った全レコードをすべて一度メモリに保存し、その後ファイルに出力している処理を見たことがあります。1レコードが数1000バイトでデータ件数が1000件程度であれば問題ありませんが、これが10万件となった場合、全レコードを蓄えるだけで数100MBになります。

データベースから1000件読み取るごとにファイル出力するロジックにした方がメモリ使用量が少なくなり、結果リソース不足で処理が遅くなることがなくなるでしょう。

まとめ

  • 性能に関する検討は要件定義、設計時から考えていきましょう。

  • 上流工程で検討することで、出戻りが少なくなりスケジュール、開発工数にもプラスになります。

  • 現在上流工程で検討していない場合は、上流工程で性能に関するスケジュールと工数を計画しましょう。

  • 性能問題は機能不具合より優先度が低くなる傾向があります。そのためシステム開発の初期段階から性能専任のチームを作成しましょう。


※ここにもう一本の記事を貼る(相互リンク)
【他の記事】



執筆者プロフィール:力石 知也
大手SIなどでアプリケーション開発からインフラ関連まで幅広く約30年経験。現在は性能改善、品質向上などの非機能関連のコンサルティングを実施。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら 
https://recruit.shiftinc.jp/career/