heroku / heroku-buildpack-php

Heroku's buildpack for PHP applications.
https://devcenter.heroku.com/categories/php
MIT License
808 stars 1.59k forks source link

New formula for calculating WEB_CONCURRENCY #685

Closed dzuelke closed 9 months ago

dzuelke commented 9 months ago

The current formula, relatively crudely, divides memory_limit by available RAM.

On machines with a lot of available RAM (especially relative to the number of CPU cores), this can result in pretty silly PHP-FPM child counts, especially with lower memory_limit values.

The new formula still caps the number of child processes at $RAM/$memory_limit, but it yields lower values for higher RAM values (or fewer cores).

Basic calculation: ceil(log_2($RAM / $CALC_BASE)) * $NUM_CORES * 2 * ($CALC_BASE / $memory_limit), where $CALC_BASE is 128M.

This, very neatly, results in exactly the same numbers as the old formula for all current Heroku dyno types, but in environments with a lot of RAM, there is now a "softer" growth in the number of PHP-FPM child processes.

There is still a linear correlation between memory_limit and PHP-FPM child count - halving the PHP memory limit will result in doubling the number of children.

Assuming a PHP memory_limit of 128M, the following comparison table for some existing Heroku dynos and fictional other environments lists the old and the new process counts:

Machine Cores Shared? RAM old new
Heroku Standard-1X dyno 8 yes 512M 4 4
Heroku Standard-2X dyno 8 yes 1G 8 8
Heroku Private-S dyno 2 no 1G 8 8
Heroku Performance-M dyno 2 no 2560M 20 20
Heroku Performance-L dyno 8 no 14G 112 112
Apple MacBook Pro M1 Pro 8 no 32G 256 128
Some High-RAM-to-CPU server 4 no 64G 512 72
Another Ultra-High-RAM server 8 no 128G 2048 176
Compute-focused box 32 no 64G 512 512*

*: capped from computed 576 to ensure all workers fit into RAM at given memory_limit

GUS-W-14634717

dzuelke commented 9 months ago

For reference, the new boot output:

Regular:

Using PHP-FPM configuration include 'fpm_custom.conf'
Available RAM is 512M Bytes
Number of CPU cores is 8
PHP memory_limit is 24M Bytes
Starting php-fpm with 21 workers...
Starting httpd...

Verbose:

Using PHP-FPM configuration include 'fpm_custom.conf'
Using PHP-FPM configuration file 'vendor/heroku/heroku-buildpack-php/conf/php/8/php-fpm.conf'
Using PHP configuration (php.ini) file '.heroku/php/etc/php/php.ini'
Using Apache2 VirtualHost-level configuration include 'vendor/heroku/heroku-buildpack-php/conf/apache2/default_include.conf'
Using Apache2 configuration file 'vendor/heroku/heroku-buildpack-php/conf/apache2/heroku.conf'
Reading available RAM from '/sys/fs/cgroup/memory/memory.limit_in_bytes'
Calculating WEB_CONCURRENCY...
Available RAM is 512M Bytes
Number of CPU cores is 8
Determining scaling factor based on a memory_limit of 128M
Scaling factor is 2
memory_limit changed by /app/.user.ini
memory_limit overridden by php_admin_value in PHP-FPM configuration
PHP memory_limit is 24M Bytes
Calculated number of workers is 170
Limiting number of workers to 21
WEB_CONCURRENCY=21
Starting log redirection...
Starting php-fpm with 21 workers...
Waiting for php-fpm to finish initializing...
Starting httpd...
Application ready for connections on port 21995.