[NGINX FASTCGI PERFORMANCE] The directives are inefficient and could be improved

Currently, all fastcgi_param bindings are located outside the ".php$" check, meaning that they are evaluated and bound to a value no matter if the user loads a .bmp or .js file or any other format.

Better performance is achieved by binding all params ONLY when the .php filetype has matched, by moving them inside the block.

Status: 
Active

Comments

I'll look into changing this..

What is the actual performance impact though?

In terms of NGINX, it's both "minor" and "significant" at the same time.

NGINX prides itself on extremely fast, asynchronous performance, with extremely high req/sec performance. By adding needless directives, it adds complexity and extra validation/variable expansion for each new connection thread, thus limiting the number of reqs/second it can handle.

True numbers? Who knows, maybe 1-2%? But it's still best to put it where it belongs: Inside the .php match-block, right before the fastcgi_pass call. That way it doesn't calculate a bunch of variables on every connection. Only when PHP is really involved.

The thing with NGINX variables is that they are runtime-expanded when-needed, rather than all being available in memory all at once. So, the more variables you request, the more work for the server before it returns the response.

In short: Yes, move it all into the PHP block.

I'll take a look at this when I get some free time.

By the way, for sub-critical requests like this you could greatly increase the chance of them being included in future Virtualmin releases by sending in a code patch.

Jason is right but still wrong.

Replace this:

server {
        server_name example.com www.example.com;
        listen 192.168.1.1:80;
        root /home/example/domains/example.com/public_html;
        index index.html index.htm index.php;
        access_log /var/log/virtualmin/example.com_access_log;
        error_log /var/log/virtualmin/example.com_error_log;
        fastcgi_param GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param SERVER_SOFTWARE nginx;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;
        fastcgi_param SCRIPT_FILENAME /home/example/domains/example.com/public_html$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param REQUEST_URI $request_uri;
        fastcgi_param DOCUMENT_URI $document_uri;
        fastcgi_param DOCUMENT_ROOT /home/example/domains/example.com/public_html;
        fastcgi_param SERVER_PROTOCOL $server_protocol;
        fastcgi_param REMOTE_ADDR $remote_addr;
        fastcgi_param REMOTE_PORT $remote_port;
        fastcgi_param SERVER_ADDR $server_addr;
        fastcgi_param SERVER_PORT $server_port;
        fastcgi_param SERVER_NAME $server_name;
        fastcgi_param HTTPS $https;
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_pass unix:/home/example/php5/php-fcgi.sock;
        }
        listen 192.168.1.1:443 ssl;
        ssl_certificate /home/example/domains/example.com/ssl.cert;
        ssl_certificate_key /home/example/domains/example.com/ssl.key;
}

With this (also restructured and tiny fixes here and there):

server {
        listen 192.168.1.1:80;
        listen 192.168.1.1:443 ssl;
        server_name example.com www.example.com;

        root /home/example/domains/example.com/public_html;
        index index.php index.htm index.html;
        charset utf-8;

        access_log /var/log/virtualmin/example.com_access_log;
        error_log /var/log/virtualmin/example.com_error_log;

        ssl_certificate /home/example/domains/example.com/ssl.cert;
        ssl_certificate_key /home/example/domains/example.com/ssl.key;

        location ~ \.php$ {
                try_files $uri =404;
                include /etc/nginx/fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass unix:/home/example/php5/php-fcgi.sock;
        }
}

/etc/nginx/fastcgi_params is installed by the official Nginx repo version and most (all?) distros. In case it doesn't exist, you can just install it for people with the following official content. Note that it does not contain "SCRIPT_FILENAME", which is a non-standard parameter that PHP relies on, which is why we have to add it ourselves, as shown above.

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

I made this little repair script for now.

pastebin.com/nhWqiW2p