> For the complete documentation index, see [llms.txt](https://kunishi.gitbook.io/web-application-textbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kunishi.gitbook.io/web-application-textbook/performance-tuning-on-webapp.md).

# Webアプリケーションの性能向上

* ボトルネック（bottleneck）
  * 性能向上を阻んでいるシステムの設計上の原因。多くの場合、システム全体から見ると小さな部分である。
* Webアプリケーションの性能（応答性）が悪い場合、ボトルネックがどこにあるか
  * クライアント（Webブラウザ）のパフォーマンス
    * HTMLレンダリング
    * JavaScriptの実行速度
  * 通信経路
    * 通信データ量
    * 通信回数
    * TCP通信回数
  * サーバの資源
    * CPU使用率
    * 同時接続数
    * メモリ使用率
    * ディスクIO
  * DBMSの性能
    * SQL問合せの実行速度
    * 非効率的なSQL問合せ
    * インデックス（索引）
    * WebサーバとRDBMS間の通信
  * 外部サービス（Webサービス）の応答性
  * ボトルネックの可能性が極めて多岐に渡るため、実際にどこがボトルネックかは計測してみないとわからない
* 代表的な対策
  * サーバの負荷分散
    * 同一構成のWebサーバを複数台用意しておいて、リクエストを分散する
    * DNSラウンドロビン: ホスト名に対して複数のIPアドレス、DNSの応答で複数のIPアドレスに分散
      * 簡単だが、DNSの仕組に依存→負荷分散が十分できないことも
      * サーバがダウンしているかどうかは考慮されない
    * ロードバランサ
      * クライアントから見ると1台のWebサーバ
      * 受け取ったリクエストを複数台のリアルサーバから1台を選択して中継
      * 正常に稼働しているサーバのみから選択
      * リクエストの中身は考慮しない
      * 専用ハードウェア、ソフトウェアの両方あり
    * リバースプロキシ
      * クライアントから見ると1台のWebサーバ
      * リクエストの中身を考慮して、適切なWebサーバにリクエストを転送
      * Webサーバからのレスポンスはリバースプロキシに返る。これをクライアントに転送
      * 主な用途例
        * リクエストURIのパスが `/image/*` だったら画像用のWebサーバに、そうでない場合はWebアプリケーションサーバに
          * Webアプリケーションサーバは、多くの場合、アプリケーション高速化のため言語処理系をメモリ上に展開→1回のリクエストを処理するメモリ使用量が多い
  * 通信量の削減
    * キャッシュサーバ
      * クライアントから見ると1台のWebサーバ
      * リクエストをそのままWebサーバに転送
      * レスポンスをクライアントに送りつつ、キャッシュサーバ上に一時保存
      * 次にクライアントから同じURIへのリクエストがあったら、一時保存されたキャッシュデータをクライアントに返す
      * 考慮すべき点
        * キャッシュをどれだけ保存すべきか（期間、容量）
        * サーバでのデータの変更をどうキャッチするか
        * ステートフルな通信にはそもそも向かない（ログインしているクライアント vs. ログインしていないクライアント）
    * その他
      * 転送データのzip圧縮
        * テキストに対しては効果あり、圧縮済みバイナリデータにはあまり効果なし
      * 画像・動画etc.の圧縮改善
        * 圧縮率をあげる
        * より圧縮率の高いフォーマットを使う
  * ディスクIO、重複する計算の削減
    * メモリキャッシュ
      * アプリケーション内部で使用するデータをサーバ上のメモリ上にキャッシュ
