Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • ドキュメント
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • ドキュメント
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku のアーキテクチャ
    • Dyno (アプリコンテナ)
    • スタック (オペレーティングシステムイメージ)
    • ネットワーキングと DNS
    • プラットフォームポリシー
    • プラットフォームの原則
  • コマンドライン
  • デプロイ
    • Git を使用したデプロイ
    • Docker によるデプロイ
    • デプロイ統合
  • 継続的デリバリー
    • 継続的統合
  • 言語サポート
    • Node.js
    • Ruby
      • Bundler の使用
      • Rails のサポート
    • Python
      • Django の使用
      • Python でのバックグランドジョブ
    • Java
      • Maven の使用
      • Java でのデータベース操作
      • Spring Boot の使用
      • Java の高度なトピック
    • PHP
    • Go
      • Go の依存関係管理
    • Scala
    • Clojure
  • データベースとデータ管理
    • Heroku Postgres
      • Postgres の基礎
      • Postgres Getting Started
      • Postgres のパフォーマンス
      • Postgres のデータ転送と保持
      • Postgres の可用性
      • Postgres の特別なトピック
    • Heroku Redis
    • Apache Kafka on Heroku
    • その他のデータストア
  • モニタリングとメトリクス
    • ログ記録
  • アプリのパフォーマンス
  • アドオン
    • すべてのアドオン
  • 共同作業
  • セキュリティ
    • アプリのセキュリティ
    • ID と認証
    • コンプライアンス
  • Heroku Enterprise
    • Private Space
      • インフラストラクチャネットワーキング
    • Enterprise Accounts
    • Enterprise Team
    • Heroku Connect (Salesforce 同期)
      • Heroku Connect の管理
      • Heroku Connect のリファレンス
      • Heroku Connect のトラブルシューティング
    • シングルサインオン (SSO)
  • パターンとベストプラクティス
  • Heroku の拡張
    • Platform API
    • アプリの Webhook
    • Heroku Labs
    • アドオンのビルド
      • アドオン開発のタスク
      • アドオン API
      • アドオンのガイドラインと要件
    • CLI プラグインのビルド
    • 開発ビルドパック
    • Dev Center
  • アカウントと請求
  • トラブルシューティングとサポート
  • Integrating with Salesforce
  • 言語サポート
  • PHP
  • PHP アプリケーションの並列性の最適化

PHP アプリケーションの並列性の最適化

日本語 — Switch to English

最終更新日 2022年11月17日(木)

Table of Contents

  • デフォルト設定と動作
  • memory_limit を使用した並列性のチューニング
  • 手動での並列性のチューニング

Heroku 上の PHP アプリケーション​は PHP-FPM FastCGI Process Manager​ の下で動作し、FastCGI プロトコルを使用して Apache または Nginx Web サーバーと通信します。

FPM は、実際の PHP アプリケーションコードを実行する子プロセスを生成して管理します。これらの各プロセスは、Web サーバーからのリクエストを一度に 1 つずつ処理します。つまり、プロセスの数を増やすと並列性が向上し、それによってトラフィックが多い状況でのアプリケーションパフォーマンスも向上します。

設定されている PHP のメモリ制限​は、アプリケーションを実行する各子プロセスに適用されます。これらの子プロセスは、終了される前にその制限までメモリを消費できます。

Premier または Signature Success Plan の Heroku Enterprise​ の顧客は、Customer Solutions Architecture (CSA) チームに、このトピックに関する詳細なガイダンスを要求​できます。ここでエキスパートコーチングセッション​について学習するか、または Salesforce の担当者にお問い合わせください。

デフォルト設定と動作

PHP-FPM

PHP-FPM は、static​ プロセス管理モードを使用して動作するように設定されます。つまり、固定された数の子プロセスが生成されます。これは、dyno インスタンスが完全に分離され、固定された RAM が割り当てられている、Heroku のような環境には最適な設定です。

生成する子プロセスの数 (PHP-FPM の pm.max_children​ 設定によって制御される) は、Heroku によって適切な値に自動的に設定される WEB_CONCURRENCY​ 環境変数を使用して決定されます。

WEB_CONCURRENCY のデフォルト値

アプリケーションで複数の buildpack​ が使用されている場合、PHP buildpack​ (アプリケーションの第一言語の buildpack) が他の言語の buildpack の後で​実行されるようにする必要があります。そうしない場合、PHP buildpack の後で実行された buildpack の WEB_CONCURRENCY​ のデフォルトがアプリケーションに適用されることがあります。

たとえば、heroku/nodejs​ buildpack を heroku/php​ と同時に使用するとき、heroku/nodejs​ buildpack が heroku/php​ buildpack の後に実行された場合、WEB_CONCURRENCY​ のデフォルトは正しくない値になります。

アプリケーションを起動すると、dyno タイプ​が自動的に検出され、WEB_CONCURRENCY​ 環境変数は、その dyno 上の使用可能な RAM の量を各 PHP プロセスに対して設定されているメモリ制限で割った値に設定されます。

$ heroku ps:scale web=1:standard-2x
$ heroku logs
2020-02-06T14:52:40… heroku[web.1]: State changed from down to starting
2020-02-06T14:52:42… heroku[web.1]: Starting process with command `heroku-php-apache2`
2020-02-06T14:52:43… app[web.1]: Detected 1073741824 Bytes of RAM
2020-02-06T14:52:43… app[web.1]: PHP memory_limit is 128M Bytes
2020-02-06T14:52:43… app[web.1]: Starting php-fpm with 8 workers...
2020-02-06T14:52:43… app[web.1]: Starting httpd...
2020-02-06T14:52:44… heroku[web.1]: State changed from starting to up

Heroku 上のデフォルトの memory_limit​ は、対応する PHP バージョンのデフォルト値です。現在は、PHP のすべてのバージョンで 128 MB です。

つまり、次の設定が標準で適用されます。

​dyno タイプ​使用可能な RAM​PHP ​memory_limitWEB_​CONCURRENCY
​Eco、Basic、Standard-1x​512 MB​128 MB​4
​Standard-2X​1024 MB​128 MB​8
​Performance-M​2.5 GB​128 MB​20
​Performance-L​14 GB​128 MB​112​1
​1​: ​​WEB_CONCURRENCY​ のデフォルト値は、7.4 より前の PHP バージョンでは 48 です。

下位互換性のために、performance-l​ dyno タイプ​のデフォルト値では、7.4 より前の PHP バージョンで使用可能なメモリ量のすべては利用されません。Heroku で自動的に割り当てられる数を超える数のプロセスを使用したい場合は、このドキュメントの「手動での並列性のチューニング​」のセクションで概説されている手法を使用してください。

アプリケーションが各リクエストで、完全な飽和状態でそのメモリ制限全体を消費することはめったにない、つまり dyno はデフォルトでは少し過剰に購読されている​ため、これらのデフォルト値は、PHP-FPM マスタープロセスまたは Web サーバープロセスの “余裕” をまったく残さないように意図的に選択されています。

子プロセスの数 (さらには、並列に処理できるリクエストの数) を増やすには、単にアプリケーションの memory_limit​ 設定を小さくします。メモリ制限は、Heroku 上の PHP アプリケーションの並列性を調整するための主な方法です。

memory_limit を使用した並列性のチューニング

PHP-FPM の memory_limit の設定

.user.ini を使用したメモリ制限の設定

メモリ制限の設定が含まれている .user.ini​ 設定ファイル​は、アプリケーションのドキュメントルート​に配置できます。これは、デフォルトではアプリケーションの最上位レベルのディレクトリです。たとえば、アプリケーションの 64 MB のメモリ制限を設定する場合、.user.ini​ の内容は次のようになります。

memory_limit = 64M

ここでは “M​” サフィックスを使用してメガバイトを示すために使用されている、PHP に必要な正しい省略表記​に特に注意してください。

Procfile​ コマンド引数を使用して設定​している場合、アプリケーションのドキュメントルートはアプリケーションの最上位レベルのディレクトリとは異なる可能性があります。

このファイルを使用してアプリをデプロイし、アプリケーションの再起動を監視すると、ワーカーの数が特定の (たとえば、Standard-1X dyno 用の) メモリ制限に対して自動的に調整されたことに気が付きます。

$ heroku logs
2019-01-15T07:51:24.476056+00:00 heroku[web.1]: State changed from down to starting
2019-01-15T07:51:30.765076+00:00 heroku[web.1]: Starting process with command `heroku-php-apache2`
2019-01-15T07:51:33.188816+00:00 app[web.1]: Optimizing defaults for 1X dyno...
2019-01-15T07:51:33.370674+00:00 app[web.1]: 8 processes at 64MB memory limit.
2019-01-15T07:51:33.414407+00:00 app[web.1]: Starting php-fpm...
2019-01-15T07:51:33.414423+00:00 app[web.1]: Starting httpd...
2019-01-15T07:51:35.865579+00:00 heroku[web.1]: State changed from starting to up

dyno の起動時に Heroku によってメモリ制限が決定されるときにドキュメントルートのサブディレクトリ内の追加の .user.ini​ ファイルは評価されません​が、このようなディレクトリ内の PHP ファイルへのリクエストを処理するときに、記載されているように実行時に有効になる​ため、アプリケーションのサブディレクトリごとに memory_limit​ 設定が異なる非常に稀な (また、絶対にお勧めできない) ケースではこれを念頭に置いておいてください。

PHP-FPM 設定を使用したメモリ制限の設定

.user.ini​ ファイルの代わりに、PHP-FPM 設定インクルード​を使用して、php_value​ または php_admin_value​ ディレクティブを追加して memory_limit​ 設定を変更することもできます。たとえば、アプリケーションの 64 MB のメモリ制限を設定するには、次の内容を持つ、たとえば fpm_custom.conf​ という名前のファイルを作成します。

php_value[memory_limit] = 64M

これらの設定を有効にするには、設定がロードされるように、Procfile​ コマンドで -F​ オプションを使用する必要があります。

web: heroku-php-apache2 -F fpm_custom.conf

新しい fpm_custom.conf​ と変更された Procfile​ を使用してアプリをデプロイし、アプリケーションの再起動を監視すると、ワーカーの数が特定の (たとえば、Standard-1X dyno 用の) メモリ制限に対して自動的に調整されたことに気が付きます。

$ heroku logs
2019-01-15T07:51:24.476056+00:00 heroku[web.1]: State changed from down to starting
2019-01-15T07:51:30.765076+00:00 heroku[web.1]: Starting process with command `heroku-php-apache2 -F fpm_custom.conf`
2019-01-15T07:51:33.109122+00:00 app[web.1]: Using PHP-FPM configuration include 'fpm_custom.conf'
2019-01-15T07:51:33.188816+00:00 app[web.1]: Optimizing defaults for 1X dyno...
2019-01-15T07:51:33.370674+00:00 app[web.1]: 8 processes at 64MB memory limit.
2019-01-15T07:51:33.414407+00:00 app[web.1]: Starting php-fpm...
2019-01-15T07:51:33.414423+00:00 app[web.1]: Starting httpd...
2019-01-15T07:51:35.865579+00:00 heroku[web.1]: State changed from starting to up

memory_limit の実行時の変更

計算に使用されるメモリ制限は起動時に決定されるため、ini_set("memory_limit", ...)​ を使用して実行時にメモリ制限を変更しても並列性には影響を与えません​。

ini_set()​ を使用して実行時にメモリ制限を最初に設定された値を超えて増やしている多数のプロセスがあり、これらのプロセスが実際にその追加のメモリを消費している場合は、アプリケーションがディスクへのページングを開始したことを示す R14 エラー​が表示されることがあり、それによりパフォーマンスが低下する可能性があります。この場合は、静的な memory_limit​ を増やすか、または WEB_CONCURRENCY​ を手動でより小さい値に設定します。

多くの場合は、より高い並列性を実現するためにメモリ制限を小さくしておき、一時的により大きなメモリ制限を必要とするアプリケーション内の限られたコードパスでのみ、実行時に ini_set()​ を使用してより大きな制限を動的に設定することが望まれます。

適切なメモリ制限の決定

アプリケーションが必要とするメモリの量は、リクエスト中に処理するデータの量や、そのデータのうちのどれだけを同時にメモリ内に保持するかによって異なります。画像処理や大規模なデータベース結果セットの処理などのタスクは通常、メモリを非常に大量に使用します。

PHP での 128 MB のデフォルトのメモリ制限は、ほぼすべての種類のアプリケーションに十分な “余裕” を与えることを目的にした控えめなデフォルト値です。コードはリクエスト中にそれだけの量のメモリを消費しない可能性があるため、この制限を小さくすることはアプリケーションのパフォーマンスを最適化するための優れた方法です。

アプリケーションの最大のメモリ使用量を決定したら、増大のための安全マージンや予期しない状況 (時間の経過と共に増大するデータセットなど) を可能にするために、制限を設定するときに妥当な量の “余裕” を残すことを忘れないでください。

ローカルでのメモリ使用量の測定と最適化

開発用マシンでは、コードで (通常はスクリプトの最後に) memory_get_peak_usage()​ 関数を使用して、使用されるピークメモリを特定できます。たとえば、コードの最後にある file_put_contents("path/to/logfile", memory_get_peak_usage()."\n", FILE_APPEND);​ で負荷/機能テストを実行し、たとえば sort path/to/logfile | | tail -n 1 を使用して、そのログファイル内の最も大きな値を特定することもできます。

別の迅速かつ容易なアプローチとして、"メモリ制限を超えました" というエラーメッセージが表示され始めるまで、以降の手順で PHP で設定された (たとえば 16 MB の) メモリ制限を小さくする方法があります。64 MB の制限はたいてい安全策であり、デフォルト設定と比較して 2 倍の数のワーカープロセスが生成されます。

ローカルで (ab​、siege​、httperf​ などを使用して) 負荷テストを実行しているときは、ps​ または top​ を使用して、php-fpm​ プロセスで消費されるメモリの量を観察することもできます。

開発中にアプリケーションを適切に​プロファイリングするには、XHProf​ をお勧めします。補完的な xhprof.io GUI​ により、プロファイリングの結果のナビゲーションが簡単かつ便利になります。

ローカルでテストを実行する場合は、現実的な条件を使用することを忘れないでください (データベースの適切な大規模結果セットの使用など)。また、入力データのサイズが増加することにより不適切にスケーリングする可能性がある関数、ループ、またはアルゴリズムがないかどうかコードを監査し、それに応じてこれらを最適化することを強くお勧めします。

Heroku 上のメモリ使用量の測定

プラットフォーム固有の細かな差異は別にして、アプリケーションのメモリ消費は、入力が同じであればローカル開発環境と Heroku の間でほぼ同じであるため、まず開発環境で最適なメモリ制限を見つけるようにすることをお勧めします。

log-runtime-metrics Heroku Labs​ 機能は、メモリ消費を heroku logs​ ストリームに定期的に報告します。負荷テストを実行しているとき、メモリ使用量が、対応する dyno タイプで使用可能な量より大幅に低い場合は、メモリ制限が大きすぎる値に設定されていることを示している可能性があります。並列性を向上させ、それにより実際のメモリ使用量を増やすために、制限を小さくしてみてください。

Heroku Dashboard のアプリの概要セクションで、基本的なメモリ使用量のレポートやグラフを検査することもできます。ここには、すべての実行中の dyno の平均値が表示されることに注意してください。

New Relic​ などのアプリケーションパフォーマンス監視ツールはメモリ使用量を記録し、それをユーザーによる分析のために報告します。

Heroku Pipelines​ は、デプロイをある環境から別の環境に (たとえば、ステージング環境から本番環境に) プロモートするためのワークフローの自動化に役立ちます。これにより、非本番アプリでのメモリ使用量の変更を測定して最適化した後、それらの変更の準備ができたら本番環境にプロモートできるようにすることが簡単になります。

手動での並列性のチューニング

アプリケーションを実行している子プロセスの数を手動で設定したい場合は、環境設定を設定することによって WEB_CONCURRENCY​ 環境変数を調整できます。

たとえば、子プロセスの数を 8 に静的に設定するには、heroku config:set​ を使用します。

$ heroku config:set WEB_CONCURRENCY=8

WEB_CONCURRENCY​ を手動で設定する場合は、その値に memory_limit​ を掛けた値が、その dyno タイプ上で使用可能な RAM の量を超えないようにしてください。

これにより、アプリケーションが再起動し、起動中に dyno は静的な設定を報告します。

$ heroku logs
2019-01-15T07:51:24.476056+00:00 heroku[web.1]: State changed from down to starting
2019-01-15T07:51:30.765076+00:00 heroku[web.1]: Starting process with command `heroku-php-apache2 -F fpm_custom.conf`
2019-01-15T07:51:33.109122+00:00 app[web.1]: Using PHP-FPM configuration include 'fpm_custom.conf'
2019-01-15T07:51:33.370674+00:00 app[web.1]: Using WEB_CONCURRENCY=8 processes.
2019-01-15T07:51:33.414407+00:00 app[web.1]: Starting php-fpm...
2019-01-15T07:51:33.414423+00:00 app[web.1]: Starting httpd...
2019-01-15T07:51:35.865579+00:00 heroku[web.1]: State changed from starting to up

WEB_CONCURRENCY​ を固定値に設定する場合は、別の dyno タイプにスケーリングするときに、新しい dyno タイプ上で使用可能な異なる RAM の量を考慮に入れるためにその値の調整が必要になることがあります。

関連カテゴリー

  • PHP
PHP アプリケーションのログ記録 PHP 向けの Web サーバーおよびランタイム設定のカスタマイズ

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences