If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

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)


Hosting graciously provided by:
Python Anywhere