1
+ #!/usr/bin/env python
2
+ # (python2 or python3, don’t mind which)
1
3
'''Comparison benchmarker.'''
2
4
5
+ from __future__ import print_function
6
+ from __future__ import unicode_literals
7
+
3
8
import os
4
9
import subprocess
5
10
import sys
6
11
import time
7
- import urllib2
12
+ try :
13
+ from urllib .request import urlopen
14
+ from urllib .error import URLError
15
+ except ImportError : # py2k
16
+ from urllib2 import urlopen
17
+ from urllib2 import URLError
8
18
from contextlib import contextmanager
9
19
10
20
@@ -69,12 +79,12 @@ def spawn_server(self):
69
79
args = self .get_server_process_details ()
70
80
process = subprocess .Popen (args ,
71
81
stdout = subprocess .PIPE , stderr = subprocess .PIPE )
72
- for _ in xrange (int (self .START_CHECK_TIMEOUT /
73
- self .START_CHECK_FREQUENCY )):
82
+ for _ in range (int (self .START_CHECK_TIMEOUT /
83
+ self .START_CHECK_FREQUENCY )):
74
84
time .sleep (self .START_CHECK_FREQUENCY )
75
85
try :
76
- urllib2 . urlopen (self .root_url )
77
- except urllib2 . URLError :
86
+ urlopen (self .root_url )
87
+ except URLError :
78
88
pass
79
89
else :
80
90
break
@@ -129,9 +139,9 @@ class RustServerRunner(ServerRunner):
129
139
PLATFORM = 'rust'
130
140
131
141
# e.g. x86_64-unknown-linux-gnu
132
- HOST = subprocess .Popen (('rustc' , '--version' ),
133
- stdout = subprocess .PIPE ).communicate ()[0 ]. split (
134
- 'host: ' )[1 ].rstrip ()
142
+ rustc_version = subprocess .Popen (('rustc' , '--version' ),
143
+ stdout = subprocess .PIPE ).communicate ()[0 ]
144
+ HOST = rustc_version . split ( b 'host: ' )[1 ].rstrip ()
135
145
136
146
def __init__ (self , * args , ** kwargs ):
137
147
super (RustServerRunner , self ).__init__ (* args , ** kwargs )
@@ -142,6 +152,8 @@ def __init__(self, *args, **kwargs):
142
152
def compile_server (self ):
143
153
subprocess .Popen (('rustc' ,
144
154
'--opt-level=3' , self .source ,
155
+ '-Z' , 'lto' ,
156
+ #'-Z', 'no-landing-pads',
145
157
#'--out-dir', self.build_dir,
146
158
'-L' , '../build' , # '../build/{}/http/'.format(RustServerRunner.HOST),
147
159
# Just in case it was built with openssl support. This should
@@ -224,23 +236,52 @@ class ApacheBenchServerBencher(ServerBencher):
224
236
225
237
TOOL = 'ab'
226
238
227
- def __init__ (self , bin = 'ab' ):
239
+ def __init__ (self , bin = 'ab' , keep_alive = False ):
228
240
self .bin = bin
241
+ self .keep_alive = keep_alive
242
+ if keep_alive :
243
+ self .TOOL = 'ab-keep-alive'
229
244
230
245
def bench (self , server_runner , concurrency ):
231
- process = subprocess .Popen (
232
- (self .bin , '-n' , '100000' , '-c' , str (concurrency ),
233
- server_runner .root_url ),
234
- stdout = subprocess .PIPE , stderr = subprocess .PIPE )
246
+ args = [self .bin , '-n' , '100000' , '-c' , str (concurrency )]
247
+ if self .keep_alive :
248
+ args .append ('-k' )
249
+ args .append (server_runner .root_url )
250
+ process = subprocess .Popen (args , stdout = subprocess .PIPE ,
251
+ stderr = subprocess .PIPE )
235
252
stdout , stderr = process .communicate ()
236
253
# Might fail here if it failed. Meh; no point catching it, let it fail.
237
- rps_line = next (line for line in stdout .split ('\n ' )
238
- if line .startswith ('Requests per second:' ))
254
+ rps_line = next (line for line in stdout .split (b '\n ' )
255
+ if line .startswith (b 'Requests per second:' ))
239
256
# Matches the 2323.84 part of:
240
257
# Requests per second: 2323.84 [#/sec] (mean)
241
258
return float (rps_line .split ()[3 ])
242
259
243
260
261
+ class WrkServerBencher (ServerBencher ):
262
+
263
+ TOOL = 'wrk'
264
+
265
+ def __init__ (self , bin = 'wrk' ):
266
+ self .bin = bin
267
+
268
+ def bench (self , server_runner , concurrency ):
269
+ process = subprocess .Popen (
270
+ # defaults: --duration 10s --threads 2 --connections 10
271
+ (self .bin ,
272
+ '--threads' , str (concurrency ),
273
+ '--connections' , str (concurrency ),
274
+ server_runner .root_url ),
275
+ stdout = subprocess .PIPE , stderr = subprocess .PIPE )
276
+ stdout , stderr = process .communicate ()
277
+ # Might fail here if it failed. Meh; no point catching it, let it fail.
278
+ rps_line = next (line for line in stdout .split (b'\n ' )
279
+ if line .startswith (b'Requests/sec: ' ))
280
+ # Matches the 106353.48 part of:
281
+ # Requests/sec: 106353.48
282
+ return float (rps_line .split ()[1 ])
283
+
284
+
244
285
def runners_benchers_cross_product (runners , benchers , concurrency ):
245
286
'''
246
287
Run all combinations of runners (a :class:`ServerRunnerCollection`) and
@@ -254,9 +295,10 @@ def runners_benchers_cross_product(runners, benchers, concurrency):
254
295
255
296
256
297
def main ():
257
- ab = ApacheBenchServerBencher ()
258
- #wrk = WrkServerBencher()
259
- benchers = [ab ]
298
+ ab = ApacheBenchServerBencher (keep_alive = False )
299
+ ab_k = ApacheBenchServerBencher (keep_alive = True )
300
+ wrk = WrkServerBencher ()
301
+ benchers = [ab , ab_k , wrk ]
260
302
261
303
for server_name in ('apache_fake' ,):
262
304
runners = ServerRunnerCollection (
@@ -269,10 +311,11 @@ def main():
269
311
.format (runner .PLATFORM , runner .name )):
270
312
runner .compile_server ()
271
313
272
- for concurrency in (1 , 2 , 3 , 4 , 8 ):
314
+ for concurrency in (1 , 2 , 3 , 4 , 8 , 16 , 32 ):
273
315
for runner , bencher , result in runners_benchers_cross_product (
274
316
runners , benchers , concurrency ):
275
- print runner .PLATFORM , concurrency , bencher .TOOL , result
317
+ print (' ' .join ((runner .PLATFORM , str (concurrency ),
318
+ bencher .TOOL , str (result ))))
276
319
277
320
278
321
if __name__ == '__main__' :
0 commit comments