Blog

Testing nginx rewrite performance

Our website is 12 years old and over time we have accured quite a few URL changes. Mainly due to terminlogy changes and SEO restructures. 819 to be exact. They are rewrite rules in a nginx config file. This is a lot of regular expressions that nginx needs to execute every request. We were interested in the performance impact so we did a quick test.

We created a minimum nginx config:

$ cat /home/tom/nginx_test/nginx.conf

events {
    use epoll;
}

error_log   off;

http {
    access_log  off;

    # This folder will have our rewrite rules in it
    include /etc/nginx/rewriterules/*;

    server {
        listen 80;

        # a self-contained endpoint without any dependencies on other services.
        location / {
          expires -1; # Disable client caching (Output Header: Cache-Control: no-cache)
          default_type text/plain;
          return 200 ready;
        }
    }
}

Lets check it works

$ docker run --name loadtest -v /home/tom/nginx_test/nginx.conf:/etc/nginx/nginx.conf:ro -d -p 49666:80 nginx;
$ wget -qO- http://127.0.0.1:49666/
ready

ok, we’re ready for our first test, which is the base-case, i.e. 0 redirects. We’ll use vegeta to time the latency over 10,000 requests.

$ date;echo 'GET http://127.0.0.1:49666/' | vegeta attack -rate=1000 -duration=10s | vegeta report
Sat  2 May 07:46:32 BST 2020
Requests      [total, rate, throughput]         10000, 1000.12, 1000.10
Duration      [total, attack, wait]             9.999s, 9.999s, 170.026µs
Latencies     [min, mean, 50, 90, 95, 99, max]  99.415µs, 154.843µs, 132.126µs, 197.848µs, 292.922µs, 498.15µs, 3.898ms
Bytes In      [total, mean]                     50000, 5.00
Bytes Out     [total, mean]                     0, 0.00
Success       [ratio]                           100.00%
Status Codes  [code:count]                      200:10000

For test 2, we’ll add 819 rewrite rules to nginx and test again. I won’t show all our rewrite rules but here is a small extract to show an example of the kind of thing we’re talking about:

$ cat /home/tom/nginx_test/rewriterules.conf
...
rewrite ^/site/aboutus$ https://$http_host/about permanent;
rewrite ^/static/how-it-works-buyer$ https://$http_host/how-it-works permanent;
rewrite ^/static/how-it-works-seller$ https://$http_host/how-it-works permanent;
rewrite ^/site/joinus$ https://careers.jobscore.com/careers/peopleperhourcom permanent;
...

Lets run the same test, 10,000 requests again but this time I mount the rewriterules.conf into the nginx docker container:

$ docker stop loadtest;docker rm loadtest;docker run --name loadtest -v /home/tom/nginx_test/nginx.conf:/etc/nginx/nginx.conf:ro -v  /home/tom/nginx_test/rewriterules.conf:/etc/nginx/rewriterules.conf -d -p 49666:80 nginx;

$ date;echo 'GET http://127.0.0.1:49666/' | vegeta attack -rate=1000 -duration=10s | vegeta report
Sat  2 May 07:25:59 BST 2020
Requests      [total, rate, throughput]         10000, 1000.11, 1000.09
Duration      [total, attack, wait]             9.999s, 9.999s, 197.294µs
Latencies     [min, mean, 50, 90, 95, 99, max]  144.79µs, 191.594µs, 172.16µs, 217.622µs, 255.267µs, 562.041µs, 3.485ms
Bytes In      [total, mean]                     50000, 5.00
Bytes Out     [total, mean]                     0, 0.00
Success       [ratio]                           100.00%
Status Codes  [code:count]                      200:10000

The median latency has worsened from 132.126µs to 172.16µs. This is peanuts, but it shows the extra rewrites are having a impact to performance, however small.

Lets finish up by trying a really large number of rewrites. I took my rewriterules.conf file, did select-all, then copy and paste, paste, paste*10 until I had 10,000 rules. I ran exactly the same command as the previous test:

$ docker stop loadtest;docker rm loadtest;docker run --name loadtest -v /home/tom/nginx_test/nginx.conf:/etc/nginx/nginx.conf:ro -v  /home/tom/nginx_test/rewriterules.conf:/etc/nginx/rewriterules.conf -d -p 49666:80 nginx;

$ date;echo 'GET http://127.0.0.1:49666/' | vegeta attack -rate=1000 -duration=10s | vegeta report
Sat  2 May 07:29:11 BST 2020
Requests      [total, rate, throughput]         10000, 1000.11, 1000.01
Duration      [total, attack, wait]             10s, 9.999s, 934.258µs
Latencies     [min, mean, 50, 90, 95, 99, max]  801.745µs, 8.855ms, 906.9µs, 28.047ms, 51.096ms, 74.329ms, 467.309ms
Bytes In      [total, mean]                     50000, 5.00
Bytes Out     [total, mean]                     0, 0.00
Success       [ratio]                           100.00%
Status Codes  [code:count]                      200:10000  

The results

With no rewrites a page is served in 132.126µs. With 819 rewrites a page is served in 172.16µs. With 10,000 rewrites a page is served in 906.9µs.

The conclusion

Ngix rewrites are super fast, use as many as you want because the performance impact is negligible. We’re talking nano-seconds.

No Comment

Post A Comment