Common remark
A structure of IIS suppose several Web Sites (with Default Web Site) and several Application Pools. When you deploy web2py on IIS you would like to setup a new site and have a separate AppPool for its root application. So you have separate logs and ability to start/stop.
To setup this separate site for processing all requests to a specific hostname (in IIS6): Context menu on the site folder \ Properties \ Web Site tab \ Web Site Identification \ Advanced... and Add... new identity - exact hostname for 80 port.
Receipt 1. Web2py is started with original webserver Rocket and IIS is configured as proxy.
It is desirable if IIS default site is already in production with enabled ASP.NET, ASP or PHP applications. And web2py sites are experimental, require frequent restarting (e.g. due to change of routes.py)
1.1. Install web2py as you wish and get it running with a preferable method (e.g. at http://localhost:8000/ ):
- from command line (shortcut)
- Scheduled Task
- Service
1.2. Tune proxy from IIS
Choose some Apache mod_rewrite compatible URL rewriter with proxy support:
1.2a. Binary easily configurable Helicon ISAPI_Rewrite for $100 with Proxy support
1.2b. Free ASP.NET ManagedFusion.Rewriter. It is stable and standards compliant. There were some bugs with uploading of big files on low speed on 64-bit IIS6 - some timeout issues:
- install by instruction
- in the config file ManagedFusion.Rewriter.txt add for each host:
RewriteCond %{HTTP_HOST} ^www.appname.com$ [NC] RewriteRule ^(.*)$ http://localhost:8000/appname$1 [P,QSA,L]
and for the rest:
RewriteRule ^(/.+)$ http://%{HTTP_HOST}:8000$1 [L]
- tune routes.py in web2py folder to correctly deal with requests, eg
routes_in= ( ('/admin/(?P<a>.*)','/admin/\g<a>'), ('/(?P<app>\w+)/robots.txt','/\g<app>/static/robots.txt'), ('/(?P<app>\w+)/favicon.ico','/\g<app>/static/favicon.ico'), ('/(?P<app>\w+)/sitemap.xml','/\g<app>/static/sitemap.xml'), ('/(?P<app>\w+)/static/(?P<u>.*)','/\g<app>/static/\g<u>'), ('/(?P<app>\w+)/appadmin/(?P<u>.*)','/\g<app>/appadmin/\g<u>'), ('/(?P<app>\w+)/plugin_tagging/(?P<u>.*)','/\g<app>/plugin_tagging/\g<u>'), ('/(?P<app>\w+)/(?P<u>.*)','/\g<app>/default/\g<u>'), ) routes_out=( ('/admin(?P<stuff>.*)', '/admin\g<stuff>'), ('/\w+/static/(?P<url>.*)','/static/\g<url>'), ('/\w+/default/(?P<url>.*)','/\g<url>'), ('/\w+/manamana/(?P<url>.*)','/manamana/\g<url>'), ('/\w+/appadmin/(?P<url>.*)','/appadmin/\g<url>'), ('/\w+/plugin_tagging/(?P<url>.*)','/plugin_tagging/\g<url>'), )
Receipt 2. Web2py is called from ISAPI handler in the dedicated AppPool natively in Microsoft IIS
This configuration is production quality. It mimics recommended one for Linux+Apache, only for the native Windows environment. Also you can still run a version for testing in parallel.
2.1. Install Python 2.6
If you want test GAE on the same server dont be shy: although GAE requires Python2.5, you can add link Registry key to Pyhton2.6 installation folder so GAE will install smoothly. Hope Pyhton2.7 will work also, but 3.0 and above are not supported by web2py itself. Assume you install python in the C:\Python folder and web2py to C:\w2p.
2.1a If you have already installed binary web2py, you can continue use it for testing on http://localhost:8000. Then you need download source version of web2py and unpack it somewhere. It will be required below.
2.2. Install ISAPI module
isapi-wsgi is mature, based on pywin32. You can also try PyISAPYe (see below), but there were some bugs with big files (over 16k - its default buffer size). Install isapi-wsgi with win32 installer. It will install all needed libraries.
2.2.0 (optional) If you are not primary administrator on the server and afraid to break existing applications Try at first install simple test site to test server layers w/o web2py. Goto the C:\Python\Lib\site-packages folder and run command.
C:\Python\Lib\site-packages>python isapi_wsgi.py install
Configured Virtual Directory: isapi-wsgi-test
Extension installed
Installation complete.
Now check URL http://localhost/isapi-wsgi-test/
if you receive a 500 error on response that contains the following text:
%1 is not a valid Win32 application
see explanation at http://support.microsoft.com/kb/895976/en-us and the solution at the next chapter.
If you see normal Hello response, run:
python isapi_wsgi.py remove
and goto chapter 3 to config web2py handler.
2.2.1. 32-bit ISAPI on 64-bit IIS6
Check current mode for Web Applications. Goto C:\Inetpub\AdminScripts (below the default folder for the default site) and run
cscript.exe adsutil.vbs get W3SVC/AppPools/Enable32BitAppOnWin64
(you can use any command line interface, e.g. Win-R open window to run DOS command, print there cmd and hit Enter, then type commands "c:" and "cd C:\Inetpub\AdminScripts" or simply run:
cscript %systemdrive%\inetpub\AdminScripts\adsutil.vbs get w3svc/AppPools/Enable32bitAppOnWin64
If answer is
The parameter "Enable32BitAppOnWin64" is not set at this node.
or
Enable32BitAppOnWin64 : (BOOLEAN) False
you must switch bit mode for all your Web Server. Check all other applications, if they can be reconfigured such way(ASP.NET is switched from Prohibit in Allowed at Web Service Extension Panel, FCGI is not affected, if the same .ini-files at \windows\syswow64\inetsrv and at \windows\system32\inetsrv, ISAPI_Rewrite3 has both dll). If you are sure then execute command:
cscript %systemdrive%\inetpub\AdminScripts\adsutil.vbs set w3svc/AppPools/Enable32bitAppOnWin64 1
Then restart application pool
Note, that by default there is only 64-bit WebDAV in the extension list. If you use it add 32-bit with command:
IIsExt /AddFile %systemroot%\syswow64\inetsrv\httpext.dll 1 WEBDAV32 1 "WebDAV (32-bit)"
2.2.2. 32-bit ISAPI on 64-bit IIS7
Just set on the separate AppPool:
system.webServer/applicationPool/add@enable32BitAppOnWin64.
2.3. Configure WSGI handler
Basic ideas for a handler came from wsgihandler.py in the root of web2py distro. The key points are to access isapi_wsgi and gluon.main at once. The one comfortable way is to place both as python packages. To do this:
- copy folder "gluon" and files "VERSION" from source distro to C:\Python\Lib\site-packages folder. These are required, but can copy other files from the web2py root also. This fixes your production web2py version. Your testing version can be updated further without interpenetration.
- make accessible your applications - make a hardlink to C:\w2p\applications with help junction utility or FAR: This allows to use the same application set in production and testing environments.
junction C:\w2p\applications C:\Python\Lib\site-packages\applications
- Create file isapi_web2py.py in the C:\Python\Lib\site-packages folder. You can change name to whatever name you site, change it in the script also.
### The entry point for the ISAPI extension. def __ExtensionFactory__(): import os import sys path = os.path.dirname(os.path.abspath(__file__)) os.chdir(path) sys.path = [path]+[p for p in sys.path if not p==path] import gluon.main import isapi_wsgi application=gluon.main.wsgibase return isapi_wsgi.ISAPIThreadPoolHandler(application) ### ISAPI installation: ### python isapi_web2py.py install --server=Sitename if __name__=='__main__': from isapi.install import ISAPIParameters, ScriptMapParams, VirtualDirParameters, HandleCommandLine params = ISAPIParameters() sm = [ ScriptMapParams(Extension="*", Flags=0) ] vd = VirtualDirParameters(Name="appname", Description = "Web2py in Python", ScriptMaps = sm, ScriptMapUpdate = "replace" ) params.VirtualDirs = [vd] HandleCommandLine(params)
The second part is for an automatical installation from the command line. By default it installs the extension for virtual directory "appname" under "Default Web Site". You can look for proper parameters in C:\Python\Lib\site-packages\isapi\install.py
If you prefer to install by hand read the next paragraph.
2.3.1 Configure ISAPI extension by hand
Assume you can tune separate site for separate domain.
- Copy "C:\Python\Lib\site-packages\isapi\PyISAPI_loader.dll" to "C:\Python\Lib\site-packages\_isapi_web2py.dll" . By naming convention it will looks for *.py script with the same name w/o leading underscore. (we also have it).
- Create new site in the IIS Manager. In the "Properties \ Home directory \ Configuration... \ Mappings" add wildcard application map to this file "C:\Python\Lib\site-packages_isapi_web2py.dll". Set empty option "Verify that file exists". Remove other Application extensions.
- (optional) In the "Properties \ Home directory" you can clear all access marks, even Read. Also you can set Execute Permissions to None.
- Create new AppPool under the Application Pools to isolate python process for web2py from other threads, evoked by other IIS apps. Call it "web2py", for example. Set Recycle and Performance options. Think about it, as if you close and run web2py again (so you can clear "Recycle worker process" option and use cron in web2py for maintaining tasks). Web garden is equivalent to run several web2py at once but it is better to leave default 1. You can also choose specific account credentials to launch application with. Then choose the just created AppPool in the droplist in the "Properties \ Home directory" tab for your site.
- Set security settings for "_isapi_web2py.dll", "isapi_web2py.py " and "applications" in its original place. Add execute permission for IIS_WPG group (includes "NT AUTHORITY\NETWORK SERVICE" - default AppPool identity). If you change identity later - just add it to the group.
- In IIS panel look for "Web service Extensions" and ensure that the "isapi_web2py" extension is allowed. You can add a new one and set path to the "C:\Python\Lib\site-packages_isapi_web2py.dll" or allow "All Unknown ISAPI Extentions".
2.3.2 Configure routes
For recent versions of web2py the simplest solution is to use such "C:\Python\Lib\site-packages\routes.py" file with the same domains as in site properties ("Web Site \ Web Site Identification \ Advanced... \ Multiple identities for this Web Site"):
routers = dict( BASE = dict(default_application='appname', domains={'www.go.info': 'go', 'appname.com' : 'appname', 'super.appname.ru' : 'appname/super', }, ), )
If you want more detailed configuration see routes.example.py and router.example.py.
2.3.4 Configure common "static" directory controlled by IIS
Before doing so look at the benchmark tests below. Web2py is well optimized for static content for now. But if you want to try...
As we route all requests of our dedicated site to web2py, we must to filter static requests before on the level of whole IIS. To do this:
- Configure new virtual directory under "Default Web Site" and map its content to static folder of your default app, eg. "C:\w2p\applications\appname\static". It is easy to combine static libraries from several apps, if your rename specific style files correspondingly.
- Install and tune URL Rewrite module. I recommend Apache mod_rewrite compatible free Helicon ISAPI_Rewrite Lite or Helicon Ape
- Add to config:
RewriteCond %{HTTP_HOST} ^www\.appname\.com$ [NC] RewriteRule ^/static/(.*)$ http://localhost/static/$1 [L]
If you have no restrictions on upload files, add this:
RewriteCond %{HTTP_HOST} ^www\.appname\.com$ [NC] RewriteRule ^/download/(.*)$ /appname_uploads/$1 [L]
Don't forget to restrict domain names to a single variant to improve statistics and configuration:
RewriteCond %{HTTP_HOST} ^appname\.com$ [NC] RewriteRule ^(.*)$ http://www.appname.com$1 [R=301,L]
So you can use IIS logging and other application recycling abilities. And web2py is loaded through ISAPI dll if needed. Any timeout and cache options can be tuned with standard IIS configuration tools. If you need to "reload" web2py, just choose Recycle in context menu for "web2py" AppPool.
Also in such deployment scheme (w hardlinked applications folder) you can use the same application set simultaneously for production through 80 and 443 ports under IIS using Windows security abilities and for development with different servers (Rocket, Tornado, etc) through 8000 or else port with enabled admin app.
Receipt 2b. Web2py is called from ISAPI handler but with PyISAPIe
All steps are the same as for Receipt 2 with exception for ISAPI handler:
2b.2. Install PyISAPIe by hand
Copy "PyISAPIe.dll" file and "Http" folder from distro to "C:\Python\Lib\site-packages" to automatically include it in the python path.
Set permissions as in 2.3.1.
2b.3. Configure WSGI handler
PyISAPIe makes working directory where PyISAPIe.dll is placed. So hardlinked "applications" folder and "VERSION" and "routes.py" files will be accessible for handler script.
Change file "C:\Python\Lib\site-packages\Http\Isapi.py" so that it calls the single application :
from Http.WSGI import RunWSGI
from Http import Env
import gluon.main
import isapi_wsgi
application=gluon.main.wsgibase
Base = "/"
Exclude = ("/static",
'/appname_uploads',
)
def Request():
PathInfo = Env.PATH_INFO
# Pass through to the next handler if it's not
# part of our app.
if not PathInfo.startswith(Base):
return True
for Excl in Exclude:
if PathInfo.startswith(Excl):
return True
return RunWSGI(application, Base=Base)
In the "Exclude" variable you can set directories for direct IIS handling. It should be set together with upper "Web Sites" URL Rewriter module settings. See 2.3.4.
Also you can try 64-bit PyISAPYe, look about compiling it There is a ready binary version link in comments. Try it at your risk.
Receipt 3 Using pyISAPI_SCGI
http://code.google.com/p/pyisapi-scgi/ is a ISAPI Extension for SCGI. Not tested by me.
Setup steps are like in Receipt 2. pyISAPI_SCGI uses the same dll name convention as isapi_wsgi. So if you place _pyisapi_scgi.dll in "C:\Python\Lib\site-packages" , and point "Wildcard application maps" to it then after required permission settings (see 2.3.1) all request to IIS site will run the script pyisapi_scgi.py from the same directory. So place provided files there.
Edit file "scgi.conf" and set there proper port for SCGI Requests. Launch web2py on the same host with "C:\w2p\scgihandler.py" with the same settings. Default port - 4000.
4. Benchmark
All test made from Linux+Apache computer in the same local net with the server running IIS on 64-bit Windows Server 2003, RAM 8 Gib. vals - root site name, stireac.com - web2py application. Repeatability jitter is about 1-4 ms.
Test 1. Static file from the root. Assume all caching possibilities of IIS.
Server Software: Microsoft-IIS/6.0
Server Hostname: vals
Server Port: 80
Document Path: /jquery.js
Document Length: 78601 bytes
Concurrency Level: 10
Time taken for tests: 8.564 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 78855000 bytes
HTML transferred: 78601000 bytes
Requests per second: 116.76 [#/sec] (mean)
Time per request: 85.644 [ms] (mean)
Time per request: 8.564 [ms] (mean, across all concurrent requests)
Transfer rate: 8991.50 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 4 2.0 4 19
Processing: 7 70 234.9 25 3080
Waiting: 1 19 209.4 4 3018
Total: 7 73 235.5 27 3099
Percentage of the requests served within a certain time (ms)
50% 27
66% 34
75% 34
80% 37
90% 55
95% 336
98% 529
99% 633
100% 3099 (longest request)
Test 2. Setting Expiration to 0 for that file changes nothing and may be slightly up processing time.
Server Software: Microsoft-IIS/6.0
Server Hostname: vals
Server Port: 80
Document Path: /jquery.js
Document Length: 78601 bytes
Concurrency Level: 10
Time taken for tests: 7.026 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 78991496 bytes
HTML transferred: 78711938 bytes
Requests per second: 142.32 [#/sec] (mean)
Time per request: 70.264 [ms] (mean)
Time per request: 7.026 [ms] (mean, across all concurrent requests)
Transfer rate: 10978.56 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 4 2.2 4 20
Processing: 9 64 166.8 29 3080
Waiting: 1 12 133.2 6 3033
Total: 13 69 167.0 34 3086
Percentage of the requests served within a certain time (ms)
50% 34
66% 37
75% 40
80% 41
90% 81
95% 325
98% 374
99% 418
100% 3086 (longest request)
Test 3. Direct access to web2py-static
Server Software: Microsoft-IIS/6.0
Server Hostname: static.stireac.com
Server Port: 80
Document Path: /jquery.js
Document Length: 78601 bytes
Concurrency Level: 10
Time taken for tests: 7.014 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 78855000 bytes
HTML transferred: 78601000 bytes
Requests per second: 142.58 [#/sec] (mean)
Time per request: 70.135 [ms] (mean)
Time per request: 7.014 [ms] (mean, across all concurrent requests)
Transfer rate: 10979.76 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 4 2.1 4 10
Processing: 7 66 165.7 26 3053
Waiting: 0 10 132.2 4 2997
Total: 7 69 166.0 29 3058
Percentage of the requests served within a certain time (ms)
50% 29
66% 34
75% 39
80% 41
90% 271
95% 342
98% 377
99% 395
100% 3058 (longest request)
Test 4. URL Redirection to web2py-static
Server Software: Microsoft-IIS/6.0
Server Hostname: stireac.com
Server Port: 80
Document Path: /static/jquery.js
Document Length: 78601 bytes
Concurrency Level: 10
Time taken for tests: 7.032 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 78855000 bytes
HTML transferred: 78601000 bytes
Requests per second: 142.21 [#/sec] (mean)
Time per request: 70.316 [ms] (mean)
Time per request: 7.032 [ms] (mean, across all concurrent requests)
Transfer rate: 10951.48 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 4 2.1 4 10
Processing: 7 65 143.5 26 2980
Waiting: 0 7 92.2 4 2918
Total: 7 69 143.7 29 2986
Percentage of the requests served within a certain time (ms)
50% 29
66% 35
75% 39
80% 42
90% 262
95% 337
98% 376
99% 410
100% 2986 (longest request)
Test 5. ISAPI_WSGI handling of static file
Server Software: Microsoft-IIS/6.0
Server Hostname: stireac.com
Server Port: 80
Document Path: /static/jquery.js
Document Length: 78601 bytes
Concurrency Level: 10
Time taken for tests: 6.999 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 78855000 bytes
HTML transferred: 78601000 bytes
Requests per second: 142.88 [#/sec] (mean)
Time per request: 69.988 [ms] (mean)
Time per request: 6.999 [ms] (mean, across all concurrent requests)
Transfer rate: 11002.82 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 4 2.4 4 17
Processing: 7 65 150.5 28 2928
Waiting: 0 7 90.2 4 2856
Total: 7 69 151.1 33 2935
Percentage of the requests served within a certain time (ms)
50% 33
66% 35
75% 39
80% 40
90% 218
95% 347
98% 390
99% 662
100% 2935 (longest request)
Web forest for 5 possible trees have no impact on static file requests. In fact IIS not even launched worker processes to handle static files. It seemed it gives them out from cache. Tests for Web forests see below.
Test 6. Native Rocket: fast but with little waiting, may be because of zipping?
Server Software: Rocket
Server Hostname: vals
Server Port: 8000
Document Path: /stireac/static/jquery.js
Document Length: 78601 bytes
Concurrency Level: 10
Time taken for tests: 6.880 seconds
Complete requests: 1000
Failed requests: 1
(Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
Write errors: 0
Total transferred: 78843935 bytes
HTML transferred: 78587935 bytes
Requests per second: 145.36 [#/sec] (mean)
Time per request: 68.795 [ms] (mean)
Time per request: 6.880 [ms] (mean, across all concurrent requests)
Transfer rate: 11192.03 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 8 73.0 6 2313
Processing: 19 58 87.4 41 1839
Waiting: 3 8 2.2 8 25
Total: 22 66 113.6 47 2360
Percentage of the requests served within a certain time (ms)
50% 47
66% 51
75% 53
80% 54
90% 62
95% 127
98% 358
99% 388
100% 2360 (longest request)
Test 7. Tornado - like IIS in speed
Server Software: TornadoServer/1.2.1
Server Hostname: vals
Server Port: 8000
Document Path: /stireac/static/jquery.js
Document Length: 78601 bytes
Concurrency Level: 10
Time taken for tests: 7.177 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 78795000 bytes
HTML transferred: 78601000 bytes
Requests per second: 139.33 [#/sec] (mean)
Time per request: 71.770 [ms] (mean)
Time per request: 7.177 [ms] (mean, across all concurrent requests)
Transfer rate: 10721.56 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 6 103.6 3 3277
Processing: 8 64 169.4 25 2972
Waiting: 1 11 129.6 5 2915
Total: 8 70 203.1 27 3606
Percentage of the requests served within a certain time (ms)
50% 27
66% 33
75% 37
80% 40
90% 226
95% 330
98% 357
99% 384
100% 3606 (longest request)
Dynamic page from not compiled controller, in view there is a cycle for block rendering of a dozen items using web2py cache, where external requests keep
Test 11. Dynamic page from native Rocket
Server Software: Rocket
Server Hostname: vals
Server Port: 8000
Document Path: /stireac/homo
Document Length: 10253 bytes
Concurrency Level: 10
Time taken for tests: 36.742 seconds
Complete requests: 1000
Failed requests: 365
(Connect: 0, Receive: 0, Length: 365, Exceptions: 0)
Write errors: 0
Non-2xx responses: 365
Total transferred: 6738165 bytes
HTML transferred: 6515400 bytes
Requests per second: 27.22 [#/sec] (mean)
Time per request: 367.422 [ms] (mean)
Time per request: 36.742 [ms] (mean, across all concurrent requests)
Transfer rate: 179.09 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 2
Processing: 139 367 17.6 365 448
Waiting: 138 365 17.6 364 446
Total: 140 367 17.6 365 448
Percentage of the requests served within a certain time (ms)
50% 365
66% 369
75% 373
80% 377
90% 386
95% 398
98% 407
99% 418
100% 448 (longest request)
Test 12. Dynamic page with tornado - not compressed and also slow
Server Software: TornadoServer/1.2.1
Server Hostname: vals
Server Port: 8000
Document Path: /stireac/homo
Document Length: 10253 bytes
Concurrency Level: 10
Time taken for tests: 27.262 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 10544440 bytes
HTML transferred: 10295200 bytes
Requests per second: 36.68 [#/sec] (mean)
Time per request: 272.619 [ms] (mean)
Time per request: 27.262 [ms] (mean, across all concurrent requests)
Transfer rate: 377.72 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.2 1 4
Processing: 61 269 17.5 268 503
Waiting: 55 263 17.4 262 499
Total: 61 271 17.6 270 505
Percentage of the requests served within a certain time (ms)
50% 270
66% 272
75% 273
80% 274
90% 280
95% 285
98% 290
99% 294
100% 505 (longest request)
Test 13. Dynamic page with ISAPI_WSGI : not worse than Rocket
1 tree (default AppPool settings)
Server Software: Microsoft-IIS/6.0
Server Hostname: stireac.com
Server Port: 80
Document Path: /homo
Document Length: 10280 bytes
Concurrency Level: 10
Time taken for tests: 35.757 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 10582000 bytes
HTML transferred: 10280000 bytes
Requests per second: 27.97 [#/sec] (mean)
Time per request: 357.568 [ms] (mean)
Time per request: 35.757 [ms] (mean, across all concurrent requests)
Transfer rate: 289.01 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 196 357 41.5 355 799
Waiting: 195 355 41.6 353 797
Total: 197 357 41.6 355 800
Percentage of the requests served within a certain time (ms)
50% 355
66% 361
75% 365
80% 368
90% 377
95% 395
98% 406
99% 595
100% 800 (longest request)
5 trees!
Server Software: Microsoft-IIS/6.0
Server Hostname: stireac.com
Server Port: 80
Document Path: /homo
Document Length: 10280 bytes
Concurrency Level: 10
Time taken for tests: 7.312 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 10582000 bytes
HTML transferred: 10280000 bytes
Requests per second: 136.75 [#/sec] (mean)
Time per request: 73.124 [ms] (mean)
Time per request: 7.312 [ms] (mean, across all concurrent requests)
Transfer rate: 1413.22 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 1
Processing: 26 72 76.8 34 279
Waiting: 25 71 76.4 33 278
Total: 26 73 76.8 35 279
Percentage of the requests served within a certain time (ms)
50% 35
66% 39
75% 48
80% 104
90% 228
95% 240
98% 254
99% 261
100% 279 (longest request)
8 trees - 1 per a process core (load not reached 100% in each)
Server Software: Microsoft-IIS/6.0
Server Hostname: stireac.com
Server Port: 80
Document Path: /homo
Document Length: 10280 bytes
Concurrency Level: 10
Time taken for tests: 5.020 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 10582000 bytes
HTML transferred: 10280000 bytes
Requests per second: 199.19 [#/sec] (mean)
Time per request: 50.204 [ms] (mean)
Time per request: 5.020 [ms] (mean, across all concurrent requests)
Transfer rate: 2058.40 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 26 50 97.7 30 1023
Waiting: 25 49 97.6 29 1012
Total: 26 50 97.8 31 1023
Percentage of the requests served within a certain time (ms)
50% 31
66% 33
75% 34
80% 35
90% 97
95% 112
98% 128
99% 962
100% 1023 (longest request)
16 trees - no more queues!!!
Server Software: Microsoft-IIS/6.0
Server Hostname: stireac.com
Server Port: 80
Document Path: /homo
Document Length: 10280 bytes
Concurrency Level: 10
Time taken for tests: 3.585 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 10582000 bytes
HTML transferred: 10280000 bytes
Requests per second: 278.92 [#/sec] (mean)
Time per request: 35.853 [ms] (mean)
Time per request: 3.585 [ms] (mean, across all concurrent requests)
Transfer rate: 2882.32 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 2
Processing: 28 35 3.1 35 56
Waiting: 27 34 3.1 34 55
Total: 28 36 3.1 35 57
Percentage of the requests served within a certain time (ms)
50% 35
66% 37
75% 37
80% 38
90% 39
95% 41
98% 42
99% 45
100% 57 (longest request)
Test 14. Compiled app with 8 trees
Server Software: Microsoft-IIS/6.0
Server Hostname: stireac.com
Server Port: 80
Document Path: /homo
Document Length: 10280 bytes
Concurrency Level: 10
Time taken for tests: 2.567 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 10582000 bytes
HTML transferred: 10280000 bytes
Requests per second: 389.53 [#/sec] (mean)
Time per request: 25.672 [ms] (mean)
Time per request: 2.567 [ms] (mean, across all concurrent requests)
Transfer rate: 4025.44 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.5 0 9
Processing: 16 25 5.4 24 64
Waiting: 15 24 5.3 23 64
Total: 16 25 5.3 25 65
Percentage of the requests served within a certain time (ms)
50% 25
66% 27
75% 28
80% 29
90% 32
95% 34
98% 39
99% 45
100% 65 (longest request)
Benchmark conclusions
No much differences between handling static files with ISAPI_WSGI and IIS itself because of external caches.
Web forests is an effective tool for parallel handling of simultaneous requests for python web apps under IIS.
There are strangely long responses in 1-10% cases - some queues to workers processes.
Comments (0)