marcj / php-pm
Requires
- mkraemer/react-pcntl: 2.0.*
- monolog/monolog: ^1.3
- react/event-loop: ^0.4
- react/http: dev-master
- react/socket-client: ^0.5.0
- react/stream: ^0.4
- symfony/console: ^2.6|^3.0
- symfony/debug: ^2.6|^3.0
- symfony/process: ^2.6|^3.0
Requires (Dev)
- php-pm/httpkernel-adapter: dev-master
Suggests
- ext-event: Allows for use of a more performant event-loop implementation.
- ext-libev: Allows for use of a more performant event-loop implementation.
- ext-libevent: Allows for use of a more performant event-loop implementation.
- php-pm/httpkernel-adapter: HttpKernel adapter for Symfony and Laravel frameworks
- php-pm/zend-adapter: Zend application framework adapter
This package is auto-updated.
Last update: 2024-12-11 00:34:47 UTC
README
PHP-PM is a process manager, supercharger and load balancer for PHP applications.
It's based on ReactPHP and works best with applications that use request-response frameworks like Symfony's HTTPKernel. The approach of this is to kill the expensive bootstrap of PHP (declaring symbols, loading/parsing files) and the bootstrap of feature-rich frameworks. See Performance section for a quick hint. PHP-PM basically spawns several PHP instances as worker bootstraping your application (eg. the whole Symfony Kernel) and hold it in the memory to be prepared for every incoming request: This is why PHP-PM makes your application so fast.
More information can be found in the article: Bring High Performance Into Your PHP App (with ReactPHP)
Features
- Performance boost up to 15x (compared to PHP-FPM, Symfony applications).
- Integrated load balancer.
- Hot-Code reload (when PHP files changes).
- Static file serving for easy development procedures.
- Support for HttpKernel (Symfony/Laravel), Drupal (experimental), Zend (experimental).
Why using PPM as development server instead of vagrant, nginx or apache?
- No hassle with file permissions (www-data vs local user ids).
- No painful slow virtual-box file sync.
- Faster response times of your PHP app.
- No fighting with vagrant / virtual machine settings.
- Checkout a new project, run
ppm start
- done. (if configured withppm config
) - No hassle with domain names (/etc/hosts), just use different ports for your app without root access.
Installation
To get PHP-PM you need beside the php binary also php-cgi, which comes often with php. If not availabe try to install it:
Debian/Ubuntu (https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04)
apt-get install php7.0-cgi
Mac OS X - Homebrew (https://github.com/Homebrew/homebrew-php)
brew install php70
Mac OS X - Macports
port install php70-cgi
By default, PPM looks for a binary named php-cgi
. If your PHP installation uses
a different binary name, you can specify the full path to that binary with the php-cgi
configuration option (for example: ppm config --php-cgi=/opt/local/bin/php-cgi70
).
Global
$ git clone git@github.com:php-pm/php-pm.git $ cd php-pm $ composer install $ ln -s `pwd`/bin/ppm /usr/local/bin/ppm $ ppm --help
Per project
# change minimum-stability to dev in your composer.json (until we have a version tagged): "minimum-stability": "dev" composer require php-pm/php-pm:dev-master composer require php-pm/httpkernel-adapter:dev-master #if you have httpkernel (laravel, symfony) ./vendor/bin/ppm config --bootstrap=symfony #places a ppm.json in your directory ./vendor/bin/ppm start #reads ppm.json and starts the server like you want
Once configured (composer and ppm.json) you can start your app on your development machine or server instantly:
composer install ./vendor/bin/ppm start
When debug
is enabled, PHP-PM detects file changes and restarts its worker automatically.
Performance & Debugging tips
To get the maximum performance you should usually use --app-env=prod
with disabled
debug --debug=0
. Also make sure xdebug is disabled. Try with different amount of workers.
Usually a 10% over your cpu core count is good. Example: If you have 8 real cores (excl. hyper-threading) use --workers=9
.
If your applications supports it, try enabled concurrent requests per worker: --concurrent-requests=1
.
To get even more performance (for static file serving or for rather fast applications) try a different event loop:
If you get strange issues in your application and you have no idea where they are coming from try
using only one worker --workers=1
.
Adapter
HttpKernel for Symfony/Laravel - https://github.com/php-pm/php-pm-httpkernel
Drupal - https://github.com/php-pm/php-pm-drupal
Zend - https://github.com/php-pm/php-pm-zend
Command
Start
cd ~/my/path/to/symfony/ ppm start ppm start ~/my/path/to/symfony/ --bootstrap=Symfony --bridge=HttpKernel cd ~/my/path/to/symfony/ ./vendor/bin/ppm start
Symfony
cd my-project
composer require php-pm/httpkernel-adapter:dev-master
$ ./bin/ppm start --bootstrap=symfony
Laravel
cd my-project
composer require php-pm/httpkernel-adapter:dev-master
$ ./vendor/bin/ppm start --bootstrap=laravel
Drupal
cd my-project
composer require php-pm/httpkernel-adapter:dev-master
$ ./bin/ppm start --bootstrap=drupal
Zend
cd my-project
composer require php-pm/zend-adapter:dev-master
$ ./bin/ppm start --bridge=Zf2 --bootstrap=Zf2
Each worker starts its own HTTP Server which listens on port 5501, 5502, 5503 etc. Range is 5501 -> 5500+<workersCount>
.
You can integrate those workers directly in a load balancer like NGINX or use http://127.0.0.1:8080 directly.
Performance
6x3,2 GHz Intel, 16GB RAM. 20 concurrent, 1000 total request: ab -c 20 -n 1000 http://127.0.0.1:8080/
PHP 7, StreamSelectLoop
/usr/local/bin/php7 ./bin/ppm start ~/www/symfony--bridge=httpKernel --app-env=prod --logging=0 --debug=0 --workers=8
Static file: 2371.93 requests/s
Dynamic CMS application: 1685.80 request/s (http://jarves.io)
PHP 5.6.18, StreamSelectLoop
/usr/local/bin/php5 ./bin/ppm start ~/www/symfony --bridge=httpKernel --app-env=prod --logging=0 --debug=0 --workers=8
Static file: 1818.52 requests/s
Dynamic CMS application: 1270.30 request/s (http://jarves.io)
Issues
- Memory leaks, memory leaks and memory leaks. You will find also leaks in your application. :)
- Does not work with ExtEventLoop. (So don't install
php70-event
) - Drupal is very experimental and not fully working. Try using https://github.com/php-pm/php-pm-drupal.
- Symfony's and Laravel's profiler aren't working yet perfectly since it's still needed to reset some stuff after each request.
- Streamed responses are not streamed yet
- File upload is experimental
- No windows support due to signal handling
- Doesn't fully implement HTTP/1.1, but reactphp/http is working on it.
Please help us to fix those issues by creating pull requests. :)
Setup 1. Use external Load-Balancer
Example config for NGiNX:
upstream backend { server 127.0.0.1:5501; server 127.0.0.1:5502; server 127.0.0.1:5503; server 127.0.0.1:5504; server 127.0.0.1:5505; server 127.0.0.1:5506; } server { root /path/to/symfony/web/; server_name servername.com; location / { try_files $uri @backend; } location @backend { proxy_pass http://backend; } }
Setup 2. Use internal Load-Balancer
This setup is slower as we can't load balance incoming connections as fast as NGiNX it does, but it's perfect for testing purposes.