Added benchmark test script. Thanks to Andy Kittner!
This commit is contained in:
parent
92a64d38cf
commit
c66e306d90
25
extras/benchmark/README.txt
Normal file
25
extras/benchmark/README.txt
Normal file
@ -0,0 +1,25 @@
|
||||
Benchmark test script für OpenSlides
|
||||
------------------------------------
|
||||
|
||||
usage: bench.py [-h] [-d DELAY] [-j JOBS] [-p PAUSE] [-r REPEAT]
|
||||
[-s {home,projector,agenda,application}]
|
||||
base_url
|
||||
|
||||
|
||||
Optionen:
|
||||
-j JOBS Anzahl der zu startenden Clients
|
||||
|
||||
-d DELAY Pause zwischen dem Start der einzelnen Unterprozesse in ms
|
||||
(negativer Wert: zufällige Wartezeit zwischen 0 und abs($wert)).
|
||||
|
||||
-p PAUSE "Denkpause" zwischen den einzelnen Requests (ms).
|
||||
|
||||
-r REPEAT Anzahl der Wiederholungen der Requests (jeweils pro Unterprozess/Job)
|
||||
|
||||
-s URLSET Angabe der abzufragenden URLs
|
||||
|
||||
Basisurl wird als positional Argument angegeben.
|
||||
|
||||
|
||||
Beispiel:
|
||||
$ python bench.py -j 100 -d 50 -r 100 -s projector http://127.0.0.1:8000
|
209
extras/benchmark/bench.py
Executable file
209
extras/benchmark/bench.py
Executable file
@ -0,0 +1,209 @@
|
||||
import argparse
|
||||
import multiprocessing
|
||||
import random
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
import urlparse
|
||||
|
||||
import pycurl
|
||||
|
||||
URL_SETS = {
|
||||
"projector": [
|
||||
dict(
|
||||
path = "/projector/",
|
||||
headers = [
|
||||
"X-Requested-With: XMLHttpRequest",
|
||||
]
|
||||
),
|
||||
],
|
||||
"home": [
|
||||
"/",
|
||||
"/jsi18n/",
|
||||
"/static/styles/base.css",
|
||||
"/static/javascript/utils.js",
|
||||
"/static/javascript/jquery.js",
|
||||
"/static/images/bg-submenu.gif",
|
||||
"/static/images/bg-header.gif",
|
||||
"/static/images/logo.png",
|
||||
"/static/images/icons/dialog-information.png",
|
||||
"/static/images/icons/cross.png",
|
||||
],
|
||||
"agenda": [
|
||||
"/agenda/",
|
||||
"/static/styles/base.css",
|
||||
"/static/styles/tabledrag.css",
|
||||
"/static/javascript/utils.js",
|
||||
"/static/styles/agenda.css",
|
||||
"/static/javascript/jquery.js",
|
||||
"/jsi18n/",
|
||||
"/static/images/bg-header.gif",
|
||||
"/static/images/bg-submenu.gif",
|
||||
"/static/images/logo.png",
|
||||
"/static/images/icons/application-pdf.png",
|
||||
"/static/images/icons/cross.png",
|
||||
],
|
||||
"application": [
|
||||
"/application/",
|
||||
"/static/styles/base.css",
|
||||
"/static/javascript/utils.js",
|
||||
"/static/javascript/jquery.js",
|
||||
"/jsi18n/",
|
||||
"/static/images/bg-header.gif",
|
||||
"/static/images/bg-submenu.gif",
|
||||
"/static/images/icons/cross.png",
|
||||
"/static/images/logo.png",
|
||||
"/static/images/icons/application-pdf.png",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def nop_write(data):
|
||||
return len(data)
|
||||
|
||||
class Client(object):
|
||||
def __init__(self):
|
||||
self._c = pycurl.Curl()
|
||||
self._c.setopt(pycurl.FAILONERROR, 1)
|
||||
self._c.setopt(pycurl.FOLLOWLOCATION, 1)
|
||||
self._c.setopt(pycurl.TIMEOUT, 10)
|
||||
self._c.setopt(pycurl.WRITEFUNCTION, nop_write)
|
||||
self._c.setopt(pycurl.AUTOREFERER, 1)
|
||||
|
||||
|
||||
def request(self, r):
|
||||
if isinstance(r, basestring):
|
||||
self._c.setopt(pycurl.URL, r)
|
||||
else:
|
||||
self._c.setopt(pycurl.URL, r["url"])
|
||||
self._c.setopt(pycurl.HTTPHEADER, r["headers"])
|
||||
|
||||
try:
|
||||
self._c.perform()
|
||||
except pycurl.error as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def request_loop(pause, repeat, urls, should_quit):
|
||||
c = Client()
|
||||
|
||||
requests, errors = 0, 0
|
||||
max_time = 0
|
||||
sum_time = 0
|
||||
|
||||
urls = list(urls)
|
||||
random.shuffle(urls)
|
||||
|
||||
for x in xrange(repeat):
|
||||
if should_quit.value:
|
||||
break
|
||||
if pause:
|
||||
time.sleep(pause)
|
||||
for url in urls:
|
||||
if should_quit.value:
|
||||
break
|
||||
|
||||
requests += 1
|
||||
t0 = time.time()
|
||||
if not c.request(url):
|
||||
errors += 1
|
||||
t1 = time.time()
|
||||
|
||||
dt = t1 - t0
|
||||
sum_time += dt
|
||||
if dt > max_time:
|
||||
max_time = dt
|
||||
|
||||
return requests, errors, max_time, sum_time
|
||||
|
||||
|
||||
def worker(params, should_quit, lock):
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
opts = params["opts"]
|
||||
|
||||
pause = opts.pause / 1000.0
|
||||
res = request_loop(pause, opts.repeat, params["urls"], should_quit)
|
||||
with lock:
|
||||
params["requests"].value += res[0]
|
||||
params["errors"].value += res[1]
|
||||
params["max_request_time"].value = max((res[2], params["max_request_time"].value))
|
||||
params["sum_request_time"].value += res[3]
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-d", "--delay", type = int, default = 100)
|
||||
parser.add_argument("-j", "--jobs", type = int, default = 10)
|
||||
parser.add_argument("-p", "--pause", type = int, default = 500)
|
||||
parser.add_argument("-r", "--repeat", type = int, default = 100)
|
||||
parser.add_argument("-s", "--url-set", choices = list(URL_SETS),
|
||||
default = "projector")
|
||||
parser.add_argument("base_url")
|
||||
|
||||
opts = parser.parse_args()
|
||||
|
||||
base_url = opts.base_url
|
||||
urls = []
|
||||
for u in URL_SETS[opts.url_set]:
|
||||
if isinstance(u, basestring):
|
||||
u = urlparse.urljoin(base_url, u)
|
||||
else:
|
||||
u["url"] = urlparse.urljoin(base_url, u["path"])
|
||||
urls.append(u)
|
||||
|
||||
data = dict(
|
||||
opts = opts,
|
||||
urls = urls,
|
||||
|
||||
requests = multiprocessing.Value("i", 0),
|
||||
errors = multiprocessing.Value("i", 0),
|
||||
max_request_time = multiprocessing.Value("d", 0),
|
||||
sum_request_time = multiprocessing.Value("d", 0),
|
||||
)
|
||||
|
||||
lock = multiprocessing.Lock()
|
||||
quit = multiprocessing.Value("i", 0)
|
||||
|
||||
t0 = time.time()
|
||||
|
||||
workers = []
|
||||
for job in xrange(opts.jobs):
|
||||
p = multiprocessing.Process(target = worker,
|
||||
args = (data, quit, lock))
|
||||
p.daemon = True
|
||||
p.start()
|
||||
workers.append(p)
|
||||
|
||||
# spread out the start of each worker a bit
|
||||
delay = opts.delay
|
||||
if delay != 0:
|
||||
if delay < 0:
|
||||
time.sleep(random.randint(0, -delay) / 1000.0)
|
||||
else:
|
||||
time.sleep(delay / 1000.0)
|
||||
|
||||
try:
|
||||
for p in workers:
|
||||
p.join()
|
||||
except KeyboardInterrupt:
|
||||
quit.value = 1
|
||||
for p in workers:
|
||||
p.join()
|
||||
|
||||
t1 = time.time()
|
||||
|
||||
data["total_time"] = t1 - t0
|
||||
data["avg_request_time"] = data["sum_request_time"].value / data["requests"].value
|
||||
print("Total Requests: {requests.value}\n"
|
||||
"Errors: {errors.value}\n"
|
||||
"Jobs: {opts.jobs}\n"
|
||||
"Time: {total_time:.1f}s\n"
|
||||
"Max time per request: {max_request_time.value:.4f}s\n"
|
||||
"Avg time per request: {avg_request_time:.4f}s\n".format(**data))
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user