Hokay, so, for my report, I needed to do some benchmarking of how well my XML-RPC server could perform. So I threw together a quick little script with Twisted which allows me to make manylots of requests at once. It makes two files: times.csv (which contains the length of time each request takes) and errors.csv (which dumps any errors that are encountered along the way).
This is litterally the first revision so it’s incredibly hacky, but it does work fairly nicely.
To create the benchmarker object, you issue the following commands:
benchmark = Benchmark(200, 5000, url_of_server,method_name, ['method','params','here'])
And then to make it go:
benchmark.setupReqs() reactor.run() # start the reactor!
Here’s the code that currently makes it work. It’s not at all documented but you should kinda be able to see what it’s doing.
#!/usr/bin/env python
from twisted.web.xmlrpc import Proxy
from twisted.internet import reactor
import sys
import datetime
class Request():
def __init__(self, url, method, params):
self.url = url
self.method = method
self.params = params
self.start_time = 0
self.end_time = 0
self.value = ""
self.error = ""
self.finished = False
self.error_file = open('errors.csv','w+')
def addCallback(self, callback):
self.callback = callback
def addErrback(self, errback):
self.errback = errback
def makeRequest(self):
proxy = Proxy(self.url)
proxy.callRemote(self.method,*self.params).addCallbacks(self.retSuccess, self.retFail)
self.start_time = datetime.datetime.now()
def __returned(self):
self.end_time = datetime.datetime.now()
def retSuccess(self, value):
self.__returned()
self.finished = True
self.value = value
self.callback(self,value)
def retFail(self, error):
self.__returned()
self.finished = True
self.error = error
self.error_file.write("Error: %s" % error)
self.callback(self,error)
def isFinished(self):
return self.finished
def getTime(self):
return (self.end_time - self.start_time) # this should be a timedelta
class Benchmark():
def __init__(self, concurrent = 10, total = 100, url = 'http://localhost:7080/XMLRPC', method = 'date', params=[]):
self.url = url
self.method = method
self.params = params
self.concurrent_reqs = concurrent
self.total_reqs = total
self.open_reqs = 0
self.current_reqs = 0
self.error_file = open('errors.csv','w+')
self.req_times_file = open('times.csv','w+')
def makeLog(self, filename):
self.log_file = open(filename,'w+')
def makeRequest(self):
req = Request(self.url, self.method, self.params)
req.addCallback(self.reqSuccess)
req.addErrback(self.reqError)
req.makeRequest()
self.open_reqs = self.open_reqs + 1
def printReqDetail(self, req):
#print "Request time: %d ms" % req.getTime().microseconds
delta = req.getTime()
print delta
def reqFinished(self, req):
self.printReqDetail(req)
self.open_reqs = self.open_reqs - 1
self.current_reqs = self.current_reqs + 1 # completed requests
if ((self.current_reqs + self.open_reqs) < self.total_reqs):
self.makeRequest()
else:
if self.open_reqs == 0:
reactor.stop() # made as many requests as we wanted to
def reqSuccess(self,req,value):
self.reqFinished(req)
#print repr(value)
def reqError(self,req, error):
self.reqFinished(req)
#print 'error', error
def setupReqs(self):
for i in range(0,self.concurrent_reqs): # make the initial pool of requests
self.makeRequest()

