Recently I’ve been experimenting with TileStache tiles caching system, which is similar to TileCache and other tile caching systems in scope.
TileStache revealed itself as a powerful and flexible product and was very good to cache tiles generated with my Django-backed mapscript-powered WMS server. Caching and serving tiles with TileStache was by far faster then running the whole mapscript WMS machinery.
But I wanted to do more: if I could just convince nginx to serve the tiles directly from disk, this would have been even faster. Of course for this to work, TileStache must be configured to cache tiles on disk, which is what you normally want.
nginx is really good at serving static files and it is luckily wery flexible and easy to configure (once you know what to do).
The following configuration uses named regular expression captures and a try_files instruction to check for the tile existance, if found, the tile is served directly, if not found the internal redirect to the @django named location takes place.
The 404 trick in the base location (/) was necessary to avoid duplication of the @django location content, but there might be a better way.
nginx configuration file
server {
listen 88 default;
server_name localhost;
access_log /var/log/nginx/access.log;
rewrite "^/[a-z]{2}/(static|media)/(.*)$" /$1/$2;
root /www/django_app/;
location /media/ {
alias /www/django/contrib/admin/media/;
}
location /static/ {
alias /www/django_app/site_media/;
}
location ~ ^/(?<lang_code>..)/resource/tiles/1\.0\.0/(?<tile_path>.*)$ {
alias /tmp/stache/;
add_header X-Static super;
try_files $http_host/$lang_code/$tile_path @django;
}
location / {
add_header X-Static hit;
error_page 404 = @django;
return 404;
}
location @django {
add_header X-Static miss;
uwsgi_pass unix:///run/uwsgi/app/xxx/socket;
}
}
Results
I run the test on the production environment and these are the result:
Using TileStache
uwsgi serves the tiles through TileStache.
$ ab -c 100 -n 1000 http://www.xxx.it/it/resource/tilestache/1.0.0/track_2/11/1076/735.png
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.xxx.it (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.1.19
Server Hostname: www.xxx.it
Server Port: 80
Document Path: /it/resource/tilestache/1.0.0/track_2/11/1076/735.png
Document Length: 16915 bytes
Concurrency Level: 100
Time taken for tests: 5.680 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 17296896 bytes
HTML transferred: 16915000 bytes
Requests per second: 176.05 [#/sec] (mean)
Time per request: 568.019 [ms] (mean)
Time per request: 5.680 [ms] (mean, across all concurrent requests)
Transfer rate: 2973.76 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 3.5 0 14
Processing: 130 541 108.2 508 816
Waiting: 130 540 108.1 508 816
Total: 143 542 107.5 508 816
Percentage of the requests served within a certain time (ms)
50% 508
66% 562
75% 599
80% 627
90% 716
95% 751
98% 787
99% 803
100% 816 (longest request)
Direct serving by nginx
$ ab -c 100 -n 1000 http://www.xxx.it/it/resource/tiles/1.0.0/track_2/11/1076/735.png
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.xxx.it (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.1.19
Server Hostname: www.xxx.it
Server Port: 80
Document Path: /it/resource/tiles/1.0.0/track_2/11/1076/735.png
Document Length: 16915 bytes
Concurrency Level: 100
Time taken for tests: 0.233 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 17256000 bytes
HTML transferred: 16915000 bytes
Requests per second: 4300.28 [#/sec] (mean)
Time per request: 23.254 [ms] (mean)
Time per request: 0.233 [ms] (mean, across all concurrent requests)
Transfer rate: 72466.44 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 6 3.3 6 14
Processing: 5 16 4.2 16 25
Waiting: 1 8 4.4 7 20
Total: 11 22 3.6 22 35
Percentage of the requests served within a certain time (ms)
50% 22
66% 24
75% 25
80% 26
90% 26
95% 28
98% 30
99% 33
100% 35 (longest request)
Conclusions
Unsurprisingly, the solution with files served directly is several times faster: 24 in this test case.
Darren
For the second result s et, all oyur responses fall under “Non-2xx responses”. Why is that?
Alessandro Pasotti
@Darren,
good catch.
I’m sorry I dont’ have the testbed available anymore to check what exactly was happening.
Alessandro Pasotti
@Darren:
I’ve re-run the test on the production environment, the speed gain is 24 instead of 30 but this time the test is running fine, no strange errors.
Thanks for pointing this out.