nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.38k stars 326 forks source link

PHP performance #782

Open xxyyboy opened 1 year ago

xxyyboy commented 1 year ago

Poor performance in a complex PHP file. PHP-fpm: 80qps Nginx +unit or Unit:60

A simple PHP file, unit is more quickly than php-fpm, but a complex PHP file is more worse than php-fpm. A complex PHP: include socket, write file many requried php file,json transfer, db,redis,report ...

Maybe we need to replace more native I/O functions of PHP, using coroutine.

here is a project php-coroutine-engine, but this project is not longer updated.

tippexs commented 1 year ago

Thanks for reaching out. Do you have any more information? How did you measured the performance? What system? What PHP Script? Creating performance metrics it not simple and therefor not simple for us to reproduce without any more detailed information.

xxyyboy commented 1 year ago

Thanks for your replay,

CentOS Linux release 7.2 (Final), cpu:8 core , mem: 16GB, gcc-4.8.5, php7.1.3 with some extension, unit1.28.0

start nginx on port *.80. start fpm on port 127.0.0.1:9000 start unit on port 127.0.0.1:8300.

Pressure tool:apche ab

php7.1.3: Configure Command => './configure' '--prefix=/data/app/od-web/php71/' '--with-libdir=lib64' '--enable-bcmath' '--enable-calendar' '--enable-ctype' '--enable-dba' '--enable-dom' '--enable-exif' '--enable-fileinfo' '--enable-filter' '--enable-ftp' '--enable-hash' '--enable-intl' '--enable-json' '--enable-mbstring' '--enable-mysqlnd' '--enable-opcache' '--enable-pcntl' '--enable-phar' '--enable-posix' '--enable-session' '--enable-shmop' '--enable-simplexml' '--enable-soap' '--enable-sysvmsg' '--enable-sysvsem' '--enable-sysvshm' '--enable-sockets' '--enable-tokenizer' '--enable-wddx' '--enable-xml' '--enable-xmlreader' '--enable-xmlwriter' '--enable-zip' '--with-bz2' '--with-zlib' '--with-enchant' '--with-curl' '--with-gd' '--with-gettext' '--with-gmp' '--with-iconv' '--with-ldap' '--with-mcrypt' '--with-mysqli' '--with-openssl' '--with-pdo_mysql' '--with-snmp' '--with-tidy' '--with-xmlrpc' '--with-xsl' '--with-kerberos' '--enable-static' '--enable-shared' '--enable-embed=static' '--with-config-file-path=/data/app/od-web/php71/etc'

example: ./ab -n1000 -x100 -X127.0.0.1:80 'http://127.0.0.1:80/pxxju/v3/xpb/xxt/xnxhxr/xnxhxr_xxmmxn.php?_sxrvbxx=xms.xxt.xnxhxr&_jsvxr=xRxsult&bMxpulxc=41&xpt=gxt_bxsx_bnfx&_lxgbnUbn=248582875813&_lxgbnUc=2488528562813&_lxgbnTypx=pt&_rxxlLxgbnUc=248528813&_usxrbp=10.13.29.14&_xvxnt_c=pJx-pJ-1102155237-jgQ8uY-323-99669427&_lxgbnTxkxn=@@@G3JYprr5h&_ts=1667355575558&_sbgn=9pFx32x9p78x3x6p178FxxF090p9pF17'

you can download a Flame svg pic here: (remember download the svg ,then open with webbrowser) https://airportal.cn/828966/LjtOkR5K4z https://github.com/xxyyboy/nginx-error-log-parser/blob/master/laravel-flame-graph.svg

Most time cost in php IO functions. Maybe we can replace PHP's original IO function with coroutine,improve qps.

xxyyboy commented 1 year ago

I found Fibers or Coroutines for asynchronous programming in PHP 8.1 https://github.com/amphp/ext-fiber

joanhey commented 1 year ago

I don't think so.

Fibers and coroutines are language features, nothing to do with the webserver.

  1. PHP 7.1.3 is not supported from November 2019
  2. Please, don't use ab for benchmark, it's very old and only use http1.0, so no keepalive connections, and need a new tcp connection for every request.

I understand that unit, it's also and app server. But they can't change how work the language.

If you need more information, please do it, I'll try to help you. Thank you

tippexs commented 1 year ago

Thanks @joanhey for jumping in. Sounds like we have to share some more information about PHP performance and try to fix whats wrong with your issue #794 .

@xxyyboy Is there anything we can do for you? I can agree we can not change the way the application work or the PHP Runtime will interpret the code.

xxyyboy commented 1 year ago

Thanks, Maybe I think We should solve some PHP performance or efficiency problems, otherwise why chose Unit? I know if we want to improve PHP's performance effectively , we need to participate in the PHP Runtime Code or supply some PHP extension。 @tippexs @joanhey

lcrilly commented 1 year ago

@xxyyboy As noted, ab(1) is a poor tool for performance testing, especially because it is single-threaded.

If you think there is a performance issue with Unit or the unit-php module it would be great to see the details of your test environment.

xxyyboy commented 1 year ago

@lcrilly Thanks for your replay. Perhaps this issue has nothing to do with the test tool, it‘s related to the optimization of PHP's scrpit in IO interrupt waiting. example: read file, socket, sleep...

lcrilly commented 1 year ago

@xxyyboy anything to add?

hanikesn commented 1 year ago

It looks like the base image doesn't have opcache enabled at all. I assume it's because the -cli image is used as base layer: https://github.com/nginx/unit/blob/92ffcb89f8e145299e837438f0a0de93d73ffede/pkg/docker/Dockerfile.php8.2#L1 It also means opcache settings can't be set: https://github.com/nginx/unit/issues/785

meezaan commented 1 year ago

It looks like the base image doesn't have opcache enabled at all. I assume it's because the -cli image is used as base layer:

https://github.com/nginx/unit/blob/92ffcb89f8e145299e837438f0a0de93d73ffede/pkg/docker/Dockerfile.php8.2#L1

It also means opcache settings can't be set: #785

Opcache works just fine for me. here is my dockerfile (albeit 8.1 - I have not tested on 8.2 yet) - https://github.com/islamic-network/php/blob/master/8/8.1/Dockerfile.nunit.

meezaan commented 1 year ago

Even works in 8.2 for me. Here is the Dockerfile - https://github.com/islamic-network/php/blob/master/8/8.2/Dockerfile.nunit.

hanikesn commented 1 year ago

It works, but you have to load the opcache extension with zend_extension=opcache.so as by default it's not loaded. Afterwards it's enabled by default. But that also means everyone using the docker image will have bad results out-of-the-box.

meezaan commented 1 year ago

This may just be my lack of understanding, but opcache is a pure php concern, not the application or web server. The same stands true whether we talk about fpm or the php module for Apache.

So does it really need to be controlled via Unit?

ac000 commented 1 year ago

@meezaan

Thanks for verifying.

My feeling is this is something the user should enable if they want it.

hanikesn commented 1 year ago

So I just checked the upstream php-fpm image and saw that they're not enabling opcache out of the box by default as well. I think it makes sense to follow upstreams defaults as close as possible, even though it provides a bad user experience out of the box.

There's some guidance on that topic as well:

In many production environments, it is also recommended to (build and) enable the PHP core OPcache extension for performance. See the upstream OPcache documentation for more details.

https://hub.docker.com/_/php

I'm wondering whether there's a good spot on the nginx unit docs to mention that as well as many novice users will forget to enable it before benchmarking and blame nginx unit for the slow performance (opcache provides 2x-10x speedup).