# This file should be kept compatible with both Python 2.6 and Python >= 3.0.from __future__ import divisionfrom __future__ import print_function"""ccbench, a Python concurrency benchmark."""import timeimport osimport sysimport itertoolsimport threadingimport subprocessimport socketfrom optparse import OptionParser, SUPPRESS_HELPimport platform# Compatibilitytry:xrangeexcept NameError:xrange = rangetry:map = itertools.imapexcept AttributeError:passTHROUGHPUT_DURATION = 2.0LATENCY_PING_INTERVAL = 0.1LATENCY_DURATION = 2.0BANDWIDTH_PACKET_SIZE = 1024BANDWIDTH_DURATION = 2.0def task_pidigits():"""Pi calculation (Python)"""_map = map_count = itertools.count_islice = itertools.islicedef calc_ndigits(n):# From http://shootout.alioth.debian.org/def gen_x():return _map(lambda k: (k, 4*k + 2, 0, 2*k + 1), _count(1))def compose(a, b):aq, ar, as_, at = abq, br, bs, bt = breturn (aq * bq,aq * br + ar * bt,as_ * bq + at * bs,as_ * br + at * bt)def extract(z, j):q, r, s, t = zreturn (q*j + r) // (s*j + t)def pi_digits():z = (1, 0, 0, 1)x = gen_x()while 1:y = extract(z, 3)while y != extract(z, 4):z = compose(z, next(x))y = extract(z, 3)z = compose((10, -10*y, 0, 1), z)yield yreturn list(_islice(pi_digits(), n))return calc_ndigits, (50, )def task_regex():"""regular expression (C)"""# XXX this task gives horrendous latency results.import re# Taken from the `inspect` modulepat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)', re.MULTILINE)with open(__file__, "r") as f:arg = f.read(2000)def findall(s):t = time.time()try:return pat.findall(s)finally:print(time.time() - t)return pat.findall, (arg, )def task_sort():"""list sorting (C)"""def list_sort(l):l = l[::-1]l.sort()return list_sort, (list(range(1000)), )def task_compress_zlib():"""zlib compression (C)"""import zlibwith open(__file__, "rb") as f:arg = f.read(5000) * 3def compress(s):zlib.decompress(zlib.compress(s, 5))return compress, (arg, )def task_compress_bz2():"""bz2 compression (C)"""import bz2with open(__file__, "rb") as f:arg = f.read(3000) * 2def compress(s):bz2.compress(s)return compress, (arg, )def task_hashing():"""SHA1 hashing (C)"""import hashlibwith open(__file__, "rb") as f:arg = f.read(5000) * 30def compute(s):hashlib.sha1(s).digest()return compute, (arg, )throughput_tasks = [task_pidigits, task_regex]for mod in 'bz2', 'hashlib':try:globals()[mod] = __import__(mod)except ImportError:globals()[mod] = None# For whatever reasons, zlib gives irregular results, so we prefer bz2 or# hashlib if available.# (NOTE: hashlib releases the GIL from 2.7 and 3.1 onwards)if bz2 is not None:throughput_tasks.append(task_compress_bz2)elif hashlib is not None:throughput_tasks.append(task_hashing)else:throughput_tasks.append(task_compress_zlib)latency_tasks = throughput_tasksbandwidth_tasks = [task_pidigits]class TimedLoop:def __init__(self, func, args):self.func = funcself.args = argsdef __call__(self, start_time, min_duration, end_event, do_yield=False):step = 20niters = 0duration = 0.0_time = time.time_sleep = time.sleep_func = self.func_args = self.argst1 = start_timewhile True:for i in range(step):_func(*_args)t2 = _time()# If another thread terminated, the current measurement is invalid# => return the previous one.if end_event:return niters, durationniters += stepduration = t2 - start_timeif duration >= min_duration:end_event.append(None)return niters, durationif t2 - t1 < 0.01:# Minimize interference of measurement on overall runtimestep = step * 3 // 2elif do_yield:# OS scheduling of Python threads is sometimes so bad that we# have to force thread switching ourselves, otherwise we get# completely useless results._sleep(0.0001)t1 = t2def run_throughput_test(func, args, nthreads):assert nthreads >= 1# Warm upfunc(*args)results = []loop = TimedLoop(func, args)end_event = []if nthreads == 1:# Pure single-threaded performance, without any switching or# synchronization overhead.start_time = time.time()results.append(loop(start_time, THROUGHPUT_DURATION,end_event, do_yield=False))return resultsstarted = Falseready_cond = threading.Condition()start_cond = threading.Condition()ready = []def run():with ready_cond:ready.append(None)ready_cond.notify()with start_cond:while not started:start_cond.wait()results.append(loop(start_time, THROUGHPUT_DURATION,end_event, do_yield=True))threads = []for i in range(nthreads):threads.append(threading.Thread(target=run))for t in threads:t.setDaemon(True)t.start()# We don't want measurements to include thread startup overhead,# so we arrange for timing to start after all threads are ready.with ready_cond:while len(ready) < nthreads:ready_cond.wait()with start_cond:start_time = time.time()started = Truestart_cond.notify(nthreads)for t in threads:t.join()return resultsdef run_throughput_tests(max_threads):for task in throughput_tasks:print(task.__doc__)print()func, args = task()nthreads = 1baseline_speed = Nonewhile nthreads <= max_threads:results = run_throughput_test(func, args, nthreads)# Taking the max duration rather than average gives pessimistic# results rather than optimistic.speed = sum(r[0] for r in results) / max(r[1] for r in results)print("threads=%d: %d" % (nthreads, speed), end="")if baseline_speed is None:print(" iterations/s.")baseline_speed = speedelse:print(" ( %d %%)" % (speed / baseline_speed * 100))nthreads += 1print()LAT_END = "END"def _sendto(sock, s, addr):sock.sendto(s.encode('ascii'), addr)def _recv(sock, n):return sock.recv(n).decode('ascii')def latency_client(addr, nb_pings, interval):sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)try:_time = time.time_sleep = time.sleepdef _ping():_sendto(sock, "%r\n" % _time(), addr)# The first ping signals the parent process that we are ready._ping()# We give the parent a bit of time to notice._sleep(1.0)for i in range(nb_pings):_sleep(interval)_ping()_sendto(sock, LAT_END + "\n", addr)finally:sock.close()def run_latency_client(**kwargs):cmd_line = [sys.executable, '-E', os.path.abspath(__file__)]cmd_line.extend(['--latclient', repr(kwargs)])return subprocess.Popen(cmd_line) #, stdin=subprocess.PIPE,#stdout=subprocess.PIPE, stderr=subprocess.STDOUT)def run_latency_test(func, args, nthreads):# Create a listening socket to receive the pings. We use UDP which should# be painlessly cross-platform.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)sock.bind(("127.0.0.1", 0))addr = sock.getsockname()interval = LATENCY_PING_INTERVALduration = LATENCY_DURATIONnb_pings = int(duration / interval)results = []threads = []end_event = []start_cond = threading.Condition()started = Falseif nthreads > 0:# Warm upfunc(*args)results = []loop = TimedLoop(func, args)ready = []ready_cond = threading.Condition()def run():with ready_cond:ready.append(None)ready_cond.notify()with start_cond:while not started:start_cond.wait()loop(start_time, duration * 1.5, end_event, do_yield=False)for i in range(nthreads):threads.append(threading.Thread(target=run))for t in threads:t.setDaemon(True)t.start()# Wait for threads to be readywith ready_cond:while len(ready) < nthreads:ready_cond.wait()# Run the client and wait for the first ping(s) to arrive before# unblocking the background threads.chunks = []process = run_latency_client(addr=sock.getsockname(),nb_pings=nb_pings, interval=interval)s = _recv(sock, 4096)_time = time.timewith start_cond:start_time = _time()started = Truestart_cond.notify(nthreads)while LAT_END not in s:s = _recv(sock, 4096)t = _time()chunks.append((t, s))# Tell the background threads to stop.end_event.append(None)for t in threads:t.join()process.wait()sock.close()for recv_time, chunk in chunks:# NOTE: it is assumed that a line sent by a client wasn't received# in two chunks because the lines are very small.for line in chunk.splitlines():line = line.strip()if line and line != LAT_END:send_time = eval(line)assert isinstance(send_time, float)results.append((send_time, recv_time))return resultsdef run_latency_tests(max_threads):for task in latency_tasks:print("Background CPU task:", task.__doc__)print()func, args = task()nthreads = 0while nthreads <= max_threads:results = run_latency_test(func, args, nthreads)n = len(results)# We print out millisecondslats = [1000 * (t2 - t1) for (t1, t2) in results]#print(list(map(int, lats)))avg = sum(lats) / ndev = (sum((x - avg) ** 2 for x in lats) / n) ** 0.5print("CPU threads=%d: %d ms. (std dev: %d ms.)" % (nthreads, avg, dev), end="")print()#print(" [... from %d samples]" % n)nthreads += 1print()BW_END = "END"def bandwidth_client(addr, packet_size, duration):sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)sock.bind(("127.0.0.1", 0))local_addr = sock.getsockname()_time = time.time_sleep = time.sleepdef _send_chunk(msg):_sendto(sock, ("%r#%s\n" % (local_addr, msg)).rjust(packet_size), addr)# We give the parent some time to be ready._sleep(1.0)try:start_time = _time()end_time = start_time + duration * 2.0i = 0while _time() < end_time:_send_chunk(str(i))s = _recv(sock, packet_size)assert len(s) == packet_sizei += 1_send_chunk(BW_END)finally:sock.close()def run_bandwidth_client(**kwargs):cmd_line = [sys.executable, '-E', os.path.abspath(__file__)]cmd_line.extend(['--bwclient', repr(kwargs)])return subprocess.Popen(cmd_line) #, stdin=subprocess.PIPE,#stdout=subprocess.PIPE, stderr=subprocess.STDOUT)def run_bandwidth_test(func, args, nthreads):# Create a listening socket to receive the packets. We use UDP which should# be painlessly cross-platform.with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:sock.bind(("127.0.0.1", 0))addr = sock.getsockname()duration = BANDWIDTH_DURATIONpacket_size = BANDWIDTH_PACKET_SIZEresults = []threads = []end_event = []start_cond = threading.Condition()started = Falseif nthreads > 0:# Warm upfunc(*args)results = []loop = TimedLoop(func, args)ready = []ready_cond = threading.Condition()def run():with ready_cond:ready.append(None)ready_cond.notify()with start_cond:while not started:start_cond.wait()loop(start_time, duration * 1.5, end_event, do_yield=False)for i in range(nthreads):threads.append(threading.Thread(target=run))for t in threads:t.setDaemon(True)t.start()# Wait for threads to be readywith ready_cond:while len(ready) < nthreads:ready_cond.wait()# Run the client and wait for the first packet to arrive before# unblocking the background threads.process = run_bandwidth_client(addr=addr,packet_size=packet_size,duration=duration)_time = time.time# This will also wait for the parent to be readys = _recv(sock, packet_size)remote_addr = eval(s.partition('#')[0])with start_cond:start_time = _time()started = Truestart_cond.notify(nthreads)n = 0first_time = Nonewhile not end_event and BW_END not in s:_sendto(sock, s, remote_addr)s = _recv(sock, packet_size)if first_time is None:first_time = _time()n += 1end_time = _time()end_event.append(None)for t in threads:t.join()process.kill()return (n - 1) / (end_time - first_time)def run_bandwidth_tests(max_threads):for task in bandwidth_tasks:print("Background CPU task:", task.__doc__)print()func, args = task()nthreads = 0baseline_speed = Nonewhile nthreads <= max_threads:results = run_bandwidth_test(func, args, nthreads)speed = results#speed = len(results) * 1.0 / results[-1][0]print("CPU threads=%d: %.1f" % (nthreads, speed), end="")if baseline_speed is None:print(" packets/s.")baseline_speed = speedelse:print(" ( %d %%)" % (speed / baseline_speed * 100))nthreads += 1print()def main():usage = "usage: %prog [-h|--help] [options]"parser = OptionParser(usage=usage)parser.add_option("-t", "--throughput",action="store_true", dest="throughput", default=False,help="run throughput tests")parser.add_option("-l", "--latency",action="store_true", dest="latency", default=False,help="run latency tests")parser.add_option("-b", "--bandwidth",action="store_true", dest="bandwidth", default=False,help="run I/O bandwidth tests")parser.add_option("-i", "--interval",action="store", type="int", dest="check_interval", default=None,help="sys.setcheckinterval() value")parser.add_option("-I", "--switch-interval",action="store", type="float", dest="switch_interval", default=None,help="sys.setswitchinterval() value")parser.add_option("-n", "--num-threads",action="store", type="int", dest="nthreads", default=4,help="max number of threads in tests")# Hidden option to run the pinging and bandwidth clientsparser.add_option("", "--latclient",action="store", dest="latclient", default=None,help=SUPPRESS_HELP)parser.add_option("", "--bwclient",action="store", dest="bwclient", default=None,help=SUPPRESS_HELP)options, args = parser.parse_args()if args:parser.error("unexpected arguments")if options.latclient:kwargs = eval(options.latclient)latency_client(**kwargs)returnif options.bwclient:kwargs = eval(options.bwclient)bandwidth_client(**kwargs)returnif not options.throughput and not options.latency and not options.bandwidth:options.throughput = options.latency = options.bandwidth = Trueif options.check_interval:sys.setcheckinterval(options.check_interval)if options.switch_interval:sys.setswitchinterval(options.switch_interval)print("== %s %s (%s) ==" % (platform.python_implementation(),platform.python_version(),platform.python_build()[0],))# Processor identification often has repeated spacescpu = ' '.join(platform.processor().split())print("== %s %s on '%s' ==" % (platform.machine(),platform.system(),cpu,))print()if options.throughput:print("--- Throughput ---")print()run_throughput_tests(options.nthreads)if options.latency:print("--- Latency ---")print()run_latency_tests(options.nthreads)if options.bandwidth:print("--- I/O bandwidth ---")print()run_bandwidth_tests(options.nthreads)if __name__ == "__main__":main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。