Hello All,<br><br>First of all thanks for all the pointers in the #twisted about twisted.web being able to use threadpool. Here&#39;s the benchmark between cherryPy 3.0 and twisted.web that I promised. I hope this could serve as a reference in the future.<br>

<br><b>Testing parameters:</b><br>- Office PC: Intel(R) Pentium(R) D CPU 2.80GHz with 1GB RAM<br>- Apache bench set to 500 concurrent attempts within 30 secs<br>- LinuxMint Elyssa/Python 2.5.2/Twisted 2.5<br>- Twisted using SelectReactor<br>

- Webservers just returning &quot;Hello!&quot; after some mathematical calculation:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(random.randint(100, 300)):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angle = math.radians(random.randint(0, 45))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result += math.tanh(angle)/math.cosh(angle)<br><br clear="all"><b><br>CherryPy Results:</b><br>Concurrency Level:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 500<br>Time taken for tests:&nbsp;&nbsp; 30.1441 seconds<br>Complete requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>6421</b><br>
Failed requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>
Write errors:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>Total transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 834990 bytes<br>HTML transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 38538 bytes<br>Requests per second:&nbsp;&nbsp;&nbsp; 214.02 [#/sec] (mean)<br>Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2336.197 [ms] (mean)<br>Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.672 [ms] (mean, across all concurrent requests)<br>

Transfer rate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 27.17 [Kbytes/sec] received<br><b><br>twisted-web Results (no threading):</b><br>Concurrency Level:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 500<br>Time taken for tests:&nbsp;&nbsp; 30.35509 seconds<br>Complete requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>10051</b><br>
Failed requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>
Write errors:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>Total transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 502600 bytes<br>HTML transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 60312 bytes<br>Requests per second:&nbsp;&nbsp;&nbsp; 334.64 [#/sec] (mean)<br>Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1494.155 [ms] (mean)<br>Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.988 [ms] (mean, across all concurrent requests)<br>

Transfer rate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16.31 [Kbytes/sec] received<br><br><br><b>twisted-web Results (with threading, threadpool [min=100, max=400]):</b><br>Concurrency Level:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 500<br>Time taken for tests:&nbsp;&nbsp; 30.16998 seconds<br>Complete requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>11068</b><br>
Failed requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>Write errors:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>Total transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 553450 bytes<br>HTML transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 66414 bytes<br>Requests per second:&nbsp;&nbsp;&nbsp; 368.72 [#/sec] (mean)<br>Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1356.026 [ms] (mean)<br>
Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.712 [ms] (mean, across all concurrent requests)<br>Transfer rate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 17.99 [Kbytes/sec] received<br><br><br><b>Source Listing (using Twisted):<br></b><br><font size="1">#!/usr/bin/python<br>
from twisted.internet import reactor<br>from twisted.web import http<br>from twisted.python.threadpool import ThreadPool<br>import random, math, sys<br><br>class HTTPProtocol(http.Request):<br>&nbsp;&nbsp;&nbsp; def process(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def process_finish():<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(random.randint(100, 300)):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angle = math.radians(random.randint(0, 45))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result += math.tanh(angle)/math.cosh(angle)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.setHeader(&#39;Content-Type&#39;, &#39;text/html&#39;)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write(&quot;Hello!&quot;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.finish()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.channel.factory.app.threads_enabled:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&quot;Using threads&quot;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reactor.callFromThread(process_finish)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&quot;Not using threads&quot;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; process_finish()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>class HTTPChannel(http.HTTPChannel):<br>&nbsp;&nbsp;&nbsp; requestFactory = HTTPProtocol<br><br>class HTTPFactory(http.HTTPFactory):<br>
&nbsp;&nbsp;&nbsp; protocol = HTTPChannel<br>&nbsp;&nbsp;&nbsp; def __init__(self, app):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.app = app<br><br>&nbsp;&nbsp;&nbsp; def start(self, port=8080):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reactor.listenTCP(port, self)<br><br>class BenchmarkApplication():<br>&nbsp;&nbsp;&nbsp; def __init__(self):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.httpfactory = None<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.pool = None<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.threads_enabled = False<br><br>&nbsp;&nbsp;&nbsp; def start(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minthreads = int(sys.argv[1])<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxthreads = int(sys.argv[2])<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.pool = ThreadPool(minthreads, maxthreads)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.pool.start()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.threads_enabled = True<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print &quot;Threads enabled: MIN:%d MAX:%d&quot; % (minthreads, maxthreads)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except Exception, e:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&quot;minthreads and maxthreads is not set or malformed. Threading will be disabled&quot;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.httpfactory = HTTPFactory(self)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.httpfactory.start()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (True)<br><br>&nbsp;&nbsp;&nbsp; def end(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.pool != None:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.pool.stop()<br><br>if __name__ == &quot;__main__&quot;:<br>&nbsp;&nbsp;&nbsp; gba = BenchmarkApplication()<br>&nbsp;&nbsp;&nbsp; if gba.start():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reactor.run()<br>
&nbsp;&nbsp;&nbsp; gba.end()</font><b><br><br>Source Listing (using CherryPy):<br></b><font size="1">#!/usr/bin/python<br>import cherrypy<br>from amazilia import *<br>from amazilia import base<br>from amazilia import mysql<br>import random, math<br>
<br>class Root:<br>&nbsp;&nbsp;&nbsp; def index(self):<br>&nbsp;&nbsp;&nbsp; result = 0&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(random.randint(100, 300)):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angle = math.radians(random.randint(0, 45))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result += math.tanh(angle)/math.cosh(angle)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &quot;Hello!&quot;<br>&nbsp;&nbsp;&nbsp; index.exposed = True<br><br>root = Root()<br>cherrypy.quickstart(root)</font><b><br><br><br></b>I haven&#39;t had much time to tinker with CherryPy. Threre might be some ways to increase its performance. :)<br>
<br>---<br>Alvin <br>-- <br><a href="http://www.alvinatorsplayground.blogspot.com/" target="_blank">http://www.alvinatorsplayground.blogspot.com/</a><br>