-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbenchmark.py
110 lines (89 loc) · 3.38 KB
/
benchmark.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import requests
import re
import subprocess
from collections import defaultdict, namedtuple
from datetime import datetime
from enum import auto, Enum
from time import sleep
import numpy as np
import matplotlib.pyplot as plt
class ServerType(Enum):
gunicorn = auto()
Server = namedtuple('Server', ['module', 'server_type', 'settings'])
SERVERS = {
'flask-gunicorn-gevent': Server('flask_server', ServerType.gunicorn, ['--worker-class', 'gevent']),
'flask-gunicorn-meinheld': Server('flask_server', ServerType.gunicorn, ['--worker-class', 'meinheld.gmeinheld.MeinheldWorker']),
}
REQUESTS_SECOND_RE = re.compile(r'Requests\/sec\:\s*(?P<reqsec>\d+\.\d+)(?P<unit>[kMG])?')
UNITS = {
'k': 1_000,
'M': 1_000_000,
'G': 1_000_000_000,
}
HOST = '127.0.0.1'
PORT = 5000
def run_server(server, wk):
if server.server_type == ServerType.gunicorn:
return subprocess.Popen(
['gunicorn',"--workers={}".format(wk), "{}:app".format(server.module), '-b', "{}:{}".format(HOST, PORT)] + server.settings,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
cwd='servers',
)
else:
raise ValueError("Unknown server {}".format(server))
def test_server(server):
response = requests.get("http://{}:{}/10".format(HOST, PORT))
assert response.status_code == 200
assert server.module in response.text
def run_benchmark(path):
output = subprocess.check_output(
"wrk -c 100 -d 10s http://{}:{}/{}".format(wk, HOST, PORT, path), shell=True,
)
match = REQUESTS_SECOND_RE.search(output.decode())
requests_second = float(match.group('reqsec'))
if match.group('unit'):
requests_second = requests_second * UNITS[match.group('unit')]
return requests_second
if __name__ == '__main__':
n = 7
results = defaultdict(list)
fig, ax = plt.subplots(figsize=(20, 10))
plt.xlabel('Workers')
plt.ylabel('Requests per second')
plt.title('Performance')
index = np.arange(n)
bar_width = 0.20
opacity = 0.8
for i in range(1, n + 1):
print(f'Running with {2**i} workers.')
for name, server in SERVERS.items():
try:
print("Testing {} {}".format(name, datetime.now().isoformat()))
process = run_server(server, 2**i)
sleep(5)
test_server(server)
results[name].append(run_benchmark('10'))
finally:
process.terminate()
process.wait()
rects1 = plt.bar(index, results['flask-gunicorn-meinheld'], bar_width,
alpha=opacity,
color='b',
label='Meinheld')
rects2 = plt.bar(index + bar_width, results['flask-gunicorn-gevent'], bar_width,
alpha=opacity,
color='g',
label='Gevent')
plt.xticks(index + bar_width, (2**i for i in range(1, n + 1)))
plt.legend()
def autolabel(rects, xpos='center'):
xpos = xpos.lower()
ha = {'center': 'center', 'right': 'left', 'left': 'right'}
offset = {'center': 0.5, 'right': 0.57, 'left': 0.43}
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()*offset[xpos], 1.01*height,
'{}'.format(height), ha=ha[xpos], va='bottom')
autolabel(rects1, "left")
autolabel(rects2, "right")
plt.show()