NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

benchmark.py (8752B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\test\benchmark.py
      2 import getopt
      3 import os
      4 curdir = os.path.join(os.getcwd(), os.path.dirname(__file__))
      5 import re
      6 import sys
      7 import time
      8 import traceback
      9 import cherrypy
     10 from cherrypy._cpcompat import ntob
     11 from cherrypy import _cperror, _cpmodpy
     12 from cherrypy.lib import httputil
     13 AB_PATH = ''
     14 APACHE_PATH = 'apache'
     15 SCRIPT_NAME = '/cpbench/users/rdelon/apps/blog'
     16 __all__ = ['ABSession',
     17  'Root',
     18  'print_report',
     19  'run_standard_benchmarks',
     20  'safe_threads',
     21  'size_report',
     22  'startup',
     23  'thread_report']
     24 size_cache = {}
     25 
     26 class Root:
     27 
     28     def index(self):
     29         return '<html>\n<head>\n    <title>CherryPy Benchmark</title>\n</head>\n<body>\n    <ul>\n        <li><a href="hello">Hello, world! (14 byte dynamic)</a></li>\n        <li><a href="static/index.html">Static file (14 bytes static)</a></li>\n        <li><form action="sizer">Response of length:\n            <input type=\'text\' name=\'size\' value=\'10\' /></form>\n        </li>\n    </ul>\n</body>\n</html>'
     30 
     31     index.exposed = True
     32 
     33     def hello(self):
     34         return 'Hello, world\r\n'
     35 
     36     hello.exposed = True
     37 
     38     def sizer(self, size):
     39         resp = size_cache.get(size, None)
     40         if resp is None:
     41             size_cache[size] = resp = 'X' * int(size)
     42         return resp
     43 
     44     sizer.exposed = True
     45 
     46 
     47 cherrypy.config.update({'log.error.file': '',
     48  'environment': 'production',
     49  'server.socket_host': '127.0.0.1',
     50  'server.socket_port': 8080,
     51  'server.max_request_header_size': 0,
     52  'server.max_request_body_size': 0,
     53  'engine.deadlock_poll_freq': 0})
     54 del cherrypy.config['tools.log_tracebacks.on']
     55 del cherrypy.config['tools.log_headers.on']
     56 del cherrypy.config['tools.trailing_slash.on']
     57 appconf = {'/static': {'tools.staticdir.on': True,
     58              'tools.staticdir.dir': 'static',
     59              'tools.staticdir.root': curdir}}
     60 app = cherrypy.tree.mount(Root(), SCRIPT_NAME, appconf)
     61 
     62 class NullRequest:
     63 
     64     def __init__(self, local, remote, scheme = 'http'):
     65         pass
     66 
     67     def close(self):
     68         pass
     69 
     70     def run(self, method, path, query_string, protocol, headers, rfile):
     71         cherrypy.response.status = '200 OK'
     72         cherrypy.response.header_list = [('Content-Type', 'text/html'),
     73          ('Server', 'Null CherryPy'),
     74          ('Date', httputil.HTTPDate()),
     75          ('Content-Length', '0')]
     76         cherrypy.response.body = ['']
     77         return cherrypy.response
     78 
     79 
     80 class NullResponse:
     81     pass
     82 
     83 
     84 class ABSession:
     85     parse_patterns = [('complete_requests', 'Completed', ntob('^Complete requests:\\s*(\\d+)')),
     86      ('failed_requests', 'Failed', ntob('^Failed requests:\\s*(\\d+)')),
     87      ('requests_per_second', 'req/sec', ntob('^Requests per second:\\s*([0-9.]+)')),
     88      ('time_per_request_concurrent', 'msec/req', ntob('^Time per request:\\s*([0-9.]+).*concurrent requests\\)$')),
     89      ('transfer_rate', 'KB/sec', ntob('^Transfer rate:\\s*([0-9.]+)'))]
     90 
     91     def __init__(self, path = SCRIPT_NAME + '/hello', requests = 1000, concurrency = 10):
     92         self.path = path
     93         self.requests = requests
     94         self.concurrency = concurrency
     95 
     96     def args(self):
     97         port = cherrypy.server.socket_port
     98         return '-k -n %s -c %s http://127.0.0.1:%s%s' % (self.requests,
     99          self.concurrency,
    100          port,
    101          self.path)
    102 
    103     def run(self):
    104         global AB_PATH
    105         try:
    106             self.output = _cpmodpy.read_process(AB_PATH or 'ab', self.args())
    107         except:
    108             print _cperror.format_exc()
    109             raise
    110 
    111         for attr, name, pattern in self.parse_patterns:
    112             val = re.search(pattern, self.output, re.MULTILINE)
    113             if val:
    114                 val = val.group(1)
    115                 setattr(self, attr, val)
    116             else:
    117                 setattr(self, attr, None)
    118 
    119 
    120 safe_threads = (25, 50, 100, 200, 400)
    121 if sys.platform in ('win32',):
    122     safe_threads = (10, 20, 30, 40, 50)
    123 
    124 def thread_report(path = SCRIPT_NAME + '/hello', concurrency = safe_threads):
    125     sess = ABSession(path)
    126     attrs, names, patterns = list(zip(*sess.parse_patterns))
    127     avg = dict.fromkeys(attrs, 0.0)
    128     yield ('threads',) + names
    129     for c in concurrency:
    130         sess.concurrency = c
    131         sess.run()
    132         row = [c]
    133         for attr in attrs:
    134             val = getattr(sess, attr)
    135             if val is None:
    136                 print sess.output
    137                 row = None
    138                 break
    139             val = float(val)
    140             avg[attr] += float(val)
    141             row.append(val)
    142 
    143         if row:
    144             yield row
    145 
    146     yield ['Average'] + [ str(avg[attr] / len(concurrency)) for attr in attrs ]
    147 
    148 
    149 def size_report(sizes = (10, 100, 1000, 10000, 100000, 100000000), concurrency = 50):
    150     sess = ABSession(concurrency=concurrency)
    151     attrs, names, patterns = list(zip(*sess.parse_patterns))
    152     yield ('bytes',) + names
    153     for sz in sizes:
    154         sess.path = '%s/sizer?size=%s' % (SCRIPT_NAME, sz)
    155         sess.run()
    156         yield [sz] + [ getattr(sess, attr) for attr in attrs ]
    157 
    158 
    159 def print_report(rows):
    160     for row in rows:
    161         print ''
    162         for i, val in enumerate(row):
    163             sys.stdout.write(str(val).rjust(10) + ' | ')
    164 
    165     print ''
    166 
    167 
    168 def run_standard_benchmarks():
    169     print ''
    170     print 'Client Thread Report (1000 requests, 14 byte response body, %s server threads):' % cherrypy.server.thread_pool
    171     print_report(thread_report())
    172     print ''
    173     print 'Client Thread Report (1000 requests, 14 bytes via staticdir, %s server threads):' % cherrypy.server.thread_pool
    174     print_report(thread_report('%s/static/index.html' % SCRIPT_NAME))
    175     print ''
    176     print 'Size Report (1000 requests, 50 client threads, %s server threads):' % cherrypy.server.thread_pool
    177     print_report(size_report())
    178 
    179 
    180 def startup_modpython(req = None):
    181     global AB_PATH
    182     if cherrypy.engine.state == cherrypy._cpengine.STOPPED:
    183         if req:
    184             if 'nullreq' in req.get_options():
    185                 cherrypy.engine.request_class = NullRequest
    186                 cherrypy.engine.response_class = NullResponse
    187             ab_opt = req.get_options().get('ab', '')
    188             if ab_opt:
    189                 AB_PATH = ab_opt
    190         cherrypy.engine.start()
    191     if cherrypy.engine.state == cherrypy._cpengine.STARTING:
    192         cherrypy.engine.wait()
    193     return 0
    194 
    195 
    196 def run_modpython(use_wsgi = False):
    197     print 'Starting mod_python...'
    198     pyopts = []
    199     if '--null' in opts:
    200         pyopts.append(('nullreq', ''))
    201     if '--ab' in opts:
    202         pyopts.append(('ab', opts['--ab']))
    203     s = _cpmodpy.ModPythonServer
    204     if use_wsgi:
    205         pyopts.append(('wsgi.application', 'cherrypy::tree'))
    206         pyopts.append(('wsgi.startup', 'cherrypy.test.benchmark::startup_modpython'))
    207         handler = 'modpython_gateway::handler'
    208         s = s(port=8080, opts=pyopts, apache_path=APACHE_PATH, handler=handler)
    209     else:
    210         pyopts.append(('cherrypy.setup', 'cherrypy.test.benchmark::startup_modpython'))
    211         s = s(port=8080, opts=pyopts, apache_path=APACHE_PATH)
    212     try:
    213         s.start()
    214         run()
    215     finally:
    216         s.stop()
    217 
    218 
    219 if __name__ == '__main__':
    220     longopts = ['cpmodpy',
    221      'modpython',
    222      'null',
    223      'notests',
    224      'help',
    225      'ab=',
    226      'apache=']
    227     try:
    228         switches, args = getopt.getopt(sys.argv[1:], '', longopts)
    229         opts = dict(switches)
    230     except getopt.GetoptError:
    231         print __doc__
    232         sys.exit(2)
    233 
    234     if '--help' in opts:
    235         print __doc__
    236         sys.exit(0)
    237     if '--ab' in opts:
    238         AB_PATH = opts['--ab']
    239     if '--notests' in opts:
    240 
    241         def run():
    242             port = cherrypy.server.socket_port
    243             print 'You may now open http://127.0.0.1:%s%s/' % (port, SCRIPT_NAME)
    244             if '--null' in opts:
    245                 print 'Using null Request object'
    246 
    247 
    248     else:
    249 
    250         def run():
    251             end = time.time() - start
    252             print 'Started in %s seconds' % end
    253             if '--null' in opts:
    254                 print '\nUsing null Request object'
    255             try:
    256                 run_standard_benchmarks()
    257             except:
    258                 print _cperror.format_exc()
    259                 raise
    260             finally:
    261                 cherrypy.engine.exit()
    262 
    263 
    264     print 'Starting CherryPy app server...'
    265 
    266     class NullWriter(object):
    267 
    268         def write(self, data):
    269             pass
    270 
    271 
    272     sys.stderr = NullWriter()
    273     start = time.time()
    274     if '--cpmodpy' in opts:
    275         run_modpython()
    276     elif '--modpython' in opts:
    277         run_modpython(use_wsgi=True)
    278     else:
    279         if '--null' in opts:
    280             cherrypy.server.request_class = NullRequest
    281             cherrypy.server.response_class = NullResponse
    282         cherrypy.engine.start_with_callback(run)
    283         cherrypy.engine.block()