1+ #!/usr/bin/env python
2+ # (python2 or python3, don’t mind which)
13'''Comparison benchmarker.'''
24
5+ from __future__ import print_function
6+ from __future__ import unicode_literals
7+
38import os
49import subprocess
510import sys
611import 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
818from contextlib import contextmanager
919
1020
@@ -69,12 +79,12 @@ def spawn_server(self):
6979 args = self .get_server_process_details ()
7080 process = subprocess .Popen (args ,
7181 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 )):
7484 time .sleep (self .START_CHECK_FREQUENCY )
7585 try :
76- urllib2 . urlopen (self .root_url )
77- except urllib2 . URLError :
86+ urlopen (self .root_url )
87+ except URLError :
7888 pass
7989 else :
8090 break
@@ -129,9 +139,9 @@ class RustServerRunner(ServerRunner):
129139 PLATFORM = 'rust'
130140
131141 # 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 ()
135145
136146 def __init__ (self , * args , ** kwargs ):
137147 super (RustServerRunner , self ).__init__ (* args , ** kwargs )
@@ -142,6 +152,8 @@ def __init__(self, *args, **kwargs):
142152 def compile_server (self ):
143153 subprocess .Popen (('rustc' ,
144154 '--opt-level=3' , self .source ,
155+ '-Z' , 'lto' ,
156+ #'-Z', 'no-landing-pads',
145157 #'--out-dir', self.build_dir,
146158 '-L' , '../build' , # '../build/{}/http/'.format(RustServerRunner.HOST),
147159 # Just in case it was built with openssl support. This should
@@ -224,23 +236,52 @@ class ApacheBenchServerBencher(ServerBencher):
224236
225237 TOOL = 'ab'
226238
227- def __init__ (self , bin = 'ab' ):
239+ def __init__ (self , bin = 'ab' , keep_alive = False ):
228240 self .bin = bin
241+ self .keep_alive = keep_alive
242+ if keep_alive :
243+ self .TOOL = 'ab-keep-alive'
229244
230245 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 )
235252 stdout , stderr = process .communicate ()
236253 # 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:' ))
239256 # Matches the 2323.84 part of:
240257 # Requests per second: 2323.84 [#/sec] (mean)
241258 return float (rps_line .split ()[3 ])
242259
243260
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+
244285def runners_benchers_cross_product (runners , benchers , concurrency ):
245286 '''
246287 Run all combinations of runners (a :class:`ServerRunnerCollection`) and
@@ -254,9 +295,10 @@ def runners_benchers_cross_product(runners, benchers, concurrency):
254295
255296
256297def 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 ]
260302
261303 for server_name in ('apache_fake' ,):
262304 runners = ServerRunnerCollection (
@@ -269,10 +311,11 @@ def main():
269311 .format (runner .PLATFORM , runner .name )):
270312 runner .compile_server ()
271313
272- for concurrency in (1 , 2 , 3 , 4 , 8 ):
314+ for concurrency in (1 , 2 , 3 , 4 , 8 , 16 , 32 ):
273315 for runner , bencher , result in runners_benchers_cross_product (
274316 runners , benchers , concurrency ):
275- print runner .PLATFORM , concurrency , bencher .TOOL , result
317+ print (' ' .join ((runner .PLATFORM , str (concurrency ),
318+ bencher .TOOL , str (result ))))
276319
277320
278321if __name__ == '__main__' :
0 commit comments