Commit 5e9d2331 authored by Jason Madden's avatar Jason Madden

Reorganize benchmarks.

parent d56054cf
......@@ -108,7 +108,7 @@ leaktest: test_prelim
@${PYTHON} scripts/travis.py fold_end default
bench:
${PYTHON} src/greentest/bench_sendall.py
${PYTHON} benchmarks/bench_sendall.py --loops 3 --processes 2 --values 2 --warmups 2
travis_test_linters:
make lint
......
from __future__ import absolute_import, print_function, division
# Best run with dnsmasq configured as a caching nameserver
# with no timeouts and configured to point there via
# /etc/resolv.conf and GEVENT_RESOLVER_NAMESERVERS
# Remember to use --inherit-environ to make that work!
# dnsmasq -d --cache-size=100000 --local-ttl=1000000 --neg-ttl=10000000
# --max-ttl=100000000 --min-cache-ttl=10000000000 --no-poll --auth-ttl=100000000000
from gevent import monkey; monkey.patch_all()
import sys
import socket
import perf
import gevent
from zope.dottedname.resolve import resolve as drresolve
blacklist = {
22, 55, 68, 69, 72, 52, 94, 62, 54, 71, 73, 74, 34, 36,
83, 86, 79, 81, 98, 99, 120, 130, 152, 161, 165, 169,
172, 199, 205, 239, 235, 254, 256, 286, 299, 259, 229,
190, 185, 182, 173, 160, 158, 153, 139, 138, 131, 129,
127, 125, 116, 112, 110, 106,
}
RUN_COUNT = 15 if hasattr(sys, 'pypy_version_info') else 5
def quiet(f, n):
try:
f(n)
except socket.gaierror:
pass
def resolve_seq(res, count=10, begin=0):
for index in range(begin, count + begin):
if index in blacklist:
continue
try:
res.gethostbyname('x%s.com' % index)
except socket.gaierror:
pass
def resolve_par(res, count=10, begin=0):
gs = []
for index in range(begin, count + begin):
if index in blacklist:
continue
gs.append(gevent.spawn(quiet, res.gethostbyname, 'x%s.com' % index))
gevent.joinall(gs)
N = 300
def run_all(resolver_name, resolve):
res = drresolve('gevent.resolver.' + resolver_name + '.Resolver')
res = res()
# dnspython looks up cname aliases by default, but c-ares does not.
# dnsmasq can only cache one address with a given cname at a time,
# and many of our addresses clash on that, so dnspython is put at a
# severe disadvantage. We turn that off here.
res._getaliases = lambda hostname, family: []
if N > 150:
# 150 is the max concurrency in dnsmasq
count = N // 3
resolve(res, count=count)
resolve(res, count=count, begin=count)
resolve(res, count=count, begin=count * 2)
else:
resolve(res, count=N)
def main():
def worker_cmd(cmd, args):
cmd.extend(args.benchmark)
runner = perf.Runner(processes=5,
add_cmdline_args=worker_cmd)
all_names = 'dnspython', 'blocking', 'ares', 'thread'
runner.argparser.add_argument('benchmark',
nargs='*',
default='all',
choices=all_names + ('all',))
args = runner.parse_args()
if 'all' in args.benchmark or args.benchmark == 'all':
args.benchmark = ['all']
names = all_names
else:
names = args.benchmark
for name in names:
runner.bench_func(name + ' sequential',
run_all,
name, resolve_seq,
inner_loops=N)
runner.bench_func(name + ' parallel',
run_all,
name, resolve_par,
inner_loops=N)
if __name__ == '__main__':
main()
#! /usr/bin/env python
from __future__ import print_function
import time
from __future__ import print_function, division, absolute_import
import perf
from gevent import socket
from gevent.server import StreamServer
def recvall(socket, addr):
while socket.recv(4096):
def recvall(sock, _):
while sock.recv(4096):
pass
N = 10
runs = []
def benchmark(conn, data):
spent_total = 0
for _ in range(N):
start = perf.perf_counter()
conn.sendall(data)
spent = perf.perf_counter() - start
spent_total += spent
runs.append(spent_total)
return spent_total
def main():
runner = perf.Runner()
server = StreamServer(("127.0.0.1", 0), recvall)
server.start()
length = 50 * 0x100000
MB = 1024 * 1024
length = 50 * MB
data = b"x" * length
spent_total = 0
N = 10
conn = socket.create_connection((server.server_host, server.server_port))
for i in range(N):
start = time.time()
conn.sendall(data)
spent = time.time() - start
print("%.2f MB/s" % (length / spent / 0x100000))
spent_total += spent
runner.bench_func('sendall', benchmark, conn, data, inner_loops=N)
print("~ %.2f MB/s" % (length * N / spent_total / 0x100000))
conn.close()
server.stop()
if runs:
total = sum(runs)
avg = total / len(runs)
# This is really only true if the perf_counter counts in seconds time
print("~ %.2f MB/s" % (length * N / avg / MB))
if __name__ == "__main__":
main()
"""
Benchmarking sleep(0) performance.
"""
from __future__ import print_function
import perf
try:
xrange
except NameError:
xrange = range
N = 100
def test(loops, sleep, arg):
t0 = perf.perf_counter()
for __ in range(loops):
for _ in xrange(N):
sleep(arg)
return perf.perf_counter() - t0
def bench_gevent(loops, arg):
from gevent import sleep
from gevent import setswitchinterval
setswitchinterval(1000)
return test(loops, sleep, arg)
def bench_eventlet(loops, arg):
from eventlet import sleep
return test(loops, sleep, arg)
def main():
runner = perf.Runner()
for arg in (0, -1, 0.00001, 0.001):
runner.bench_time_func('gevent sleep(%s)' % (arg,),
bench_gevent, arg,
inner_loops=N)
runner.bench_time_func('eventlet sleep(%s)' % (arg,),
bench_eventlet, arg,
inner_loops=N)
if __name__ == '__main__':
main()
#!/bin/sh
set -e -x
PYTHON=${PYTHON:=python}
$PYTHON -c 'from __future__ import print_function; import gevent.core; print(gevent.__version__, gevent.core.get_version(), getattr(gevent.core, "get_method", lambda: "n/a")(), getattr(gevent, "get_hub", lambda: "n/a")())'
$PYTHON -mtimeit -r 6 -s'obj = Exception(); obj.x=5' 'obj.x'
$PYTHON -mtimeit -r 6 -s'from gevent import get_hub; get_hub()' 'get_hub()'
$PYTHON -mtimeit -r 6 -s'from gevent import getcurrent' 'getcurrent()'
$PYTHON -mperf timeit -s'obj = Exception(); obj.x=5' 'obj.x'
$PYTHON -mperf timeit -s'from gevent import get_hub; get_hub()' 'get_hub()'
$PYTHON -mperf timeit -s'from gevent import getcurrent' 'getcurrent()'
$PYTHON -mtimeit -r 6 -s'from gevent.lock import Semaphore; s = Semaphore()' 's.release()'
$PYTHON -mtimeit -r 6 -s'from gevent.coros import Semaphore; from gevent import spawn_raw; s = Semaphore(0)' 'spawn_raw(s.release); s.acquire()'
$PYTHON -mtimeit -r 6 -s'from gevent.coros import Semaphore; from gevent import spawn_raw; s = Semaphore(0)' 'spawn_raw(s.release); spawn_raw(s.release); spawn_raw(s.release); spawn_raw(s.release); s.acquire(); s.acquire(); s.acquire(); s.acquire()'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; f = lambda : 5' 'spawn(f)'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; f = lambda : 5' 'spawn(f).join()'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn, wait; from gevent.hub import xrange; f = lambda : 5' 'for _ in xrange(10000): spawn(f)' 'wait()'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn_raw; f = lambda : 5' 'spawn_raw(f)'
$PYTHON -mperf timeit -s'from gevent import spawn; f = lambda : 5' 'spawn(f)'
$PYTHON -mperf timeit -s'from gevent import spawn; f = lambda : 5' 'spawn(f).join()'
$PYTHON -mperf timeit -s'from gevent import spawn, wait; from gevent.hub import xrange; f = lambda : 5' 'for _ in xrange(10000): spawn(f)' 'wait()'
$PYTHON -mperf timeit -s'from gevent import spawn_raw; f = lambda : 5' 'spawn_raw(f)'
$PYTHON -mtimeit -r 6 -s'from gevent import sleep; f = lambda : 5' 'sleep(0)'
$PYTHON -mtimeit -r 6 -s'from gevent import sleep; f = lambda : 5' 'sleep(0.0001)'
benchmarks/micro_run_callback.sh
benchmarks/micro_semaphore.sh
......
#!/bin/sh
set -e -x
PYTHON=${PYTHON:=python}
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda: 5' 'for _ in xrange(1000): g.link(l)'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(10): g.link(l);' 'g.join()'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(100): g.link(l);' 'g.join()'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(1000): g.link(l);' 'g.join()'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(10000): g.link(l);' 'g.join()'
$PYTHON -mtimeit -r 6 -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(100000): g.link(l);' 'g.join()'
$PYTHON -mperf timeit -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda: 5' 'for _ in xrange(1000): g.link(l)'
$PYTHON -mperf timeit -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(10): g.link(l);' 'g.join()'
$PYTHON -mperf timeit -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(100): g.link(l);' 'g.join()'
$PYTHON -mperf timeit -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(1000): g.link(l);' 'g.join()'
$PYTHON -mperf timeit -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(10000): g.link(l);' 'g.join()'
$PYTHON -mperf timeit -s'from gevent import spawn; from gevent.hub import xrange; g = spawn(lambda: 5); l = lambda *args: 5' 'for _ in xrange(100000): g.link(l);' 'g.join()'
#!/bin/sh
set -e -x
PYTHON=${PYTHON:=python}
$PYTHON -mtimeit -r 6 -s'from gevent import get_hub; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'run_cb(f)'
$PYTHON -mtimeit -r 6 -s'from gevent import wait,get_hub; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'run_cb(f)' 'wait()'
$PYTHON -mtimeit -r 6 -s'from gevent import get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(100): run_cb(f)'
$PYTHON -mtimeit -r 6 -s'from gevent import wait,get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(100): run_cb(f)' 'wait()'
$PYTHON -mtimeit -r 6 -s'from gevent import get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(10000): run_cb(f)'
$PYTHON -mtimeit -r 6 -s'from gevent import wait,get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(10000): run_cb(f)' 'wait()'
$PYTHON -mperf timeit -s'from gevent import get_hub; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'run_cb(f)'
$PYTHON -mperf timeit -s'from gevent import wait,get_hub; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'run_cb(f)' 'wait()'
$PYTHON -mperf timeit -s'from gevent import get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(100): run_cb(f)'
$PYTHON -mperf timeit -s'from gevent import wait,get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(100): run_cb(f)' 'wait()'
$PYTHON -mperf timeit -s'from gevent import get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(10000): run_cb(f)'
$PYTHON -mperf timeit -s'from gevent import wait,get_hub; from gevent.hub import xrange; run_cb = get_hub().loop.run_callback; f = lambda : 5' 'for _ in xrange(10000): run_cb(f)' 'wait()'
#!/bin/sh
set -e -x
PYTHON=${PYTHON:=python}
$PYTHON -mtimeit -r 6 -s'from gevent.lock import Semaphore; s = Semaphore()' 's.release()'
$PYTHON -mtimeit -r 6 -s'from gevent.lock import Semaphore; from gevent import spawn_raw; s = Semaphore(0)' 'spawn_raw(s.release); s.acquire()'
$PYTHON -mtimeit -r 6 -s'from gevent.lock import Semaphore; from gevent import spawn_raw; s = Semaphore(0)' 'spawn_raw(s.release); spawn_raw(s.release); spawn_raw(s.release); spawn_raw(s.release); s.acquire(); s.acquire(); s.acquire(); s.acquire()'
$PYTHON -mperf timeit -s'from gevent.lock import Semaphore; s = Semaphore()' 's.release()'
$PYTHON -mperf timeit -s'from gevent.lock import Semaphore; from gevent import spawn_raw; s = Semaphore(0)' 'spawn_raw(s.release); s.acquire()'
$PYTHON -mperf timeit -s'from gevent.lock import Semaphore; from gevent import spawn_raw; s = Semaphore(0)' 'spawn_raw(s.release); spawn_raw(s.release); spawn_raw(s.release); spawn_raw(s.release); s.acquire(); s.acquire(); s.acquire(); s.acquire()'
#!/bin/sh
set -e -x
PYTHON=${PYTHON:=python}
$PYTHON -mtimeit -r 6 -s'from gevent import sleep; f = lambda : 5' 'sleep(0)'
$PYTHON -mtimeit -r 6 -s'from gevent import sleep; f = lambda : 5' 'sleep(0.00001)'
$PYTHON -mtimeit -r 6 -s'from gevent import sleep; f = lambda : 5' 'sleep(0.0001)'
$PYTHON -mtimeit -r 6 -s'from gevent import sleep; f = lambda : 5' 'sleep(0.001)'
$PYTHON -m perf timeit -s 'from gevent import sleep; f = lambda : 5' 'sleep(0)'
$PYTHON -m perf timeit -s 'from gevent import sleep; f = lambda : 5' 'sleep(0.00001)'
$PYTHON -m perf timeit -s 'from gevent import sleep; f = lambda : 5' 'sleep(0.0001)'
$PYTHON -m perf timeit -s 'from gevent import sleep; f = lambda : 5' 'sleep(0.001)'
......@@ -418,9 +418,16 @@ class AresFlags(AresSettingMixin, Setting):
environment_key = 'GEVENTARES_FLAGS'
class AresTimeout(AresSettingMixin, Setting):
document = True
name = 'ares_timeout'
default = None
environment_key = 'GEVENTARES_TIMEOUT'
desc = """\
.. deprecated:: 1.3a2
Prefer the :attr:`resolver_timeout` setting. If both are set,
the results are not defined.
"""
class AresTries(AresSettingMixin, Setting):
name = 'ares_tries'
......@@ -509,6 +516,27 @@ class ResolverNameservers(AresSettingMixin, Setting):
def kwarg_name(self):
return 'servers'
# Generic timeout, works for dnspython and ares
class ResolverTimeout(AresSettingMixin, Setting):
document = True
name = 'resolver_timeout'
environment_key = 'GEVENT_RESOLVER_TIMEOUT'
desc = """\
The total amount of time that the DNS resolver will spend making queries.
Only the ares and dnspython resolvers support this.
.. versionadded:: 1.3a2
"""
def _convert(self, value):
if value:
return float(value)
@property
def kwarg_name(self):
return 'timeout'
config = Config()
# Go ahead and attempt to import the loop when this class is
......
......@@ -116,6 +116,7 @@ def _dns_import_patched(name):
dns.rdata.__import__ = _dns_import_patched
resolver = dns.resolver
dTimeout = dns.resolver.Timeout
_exc_clear = getattr(sys, 'exc_clear', lambda: None)
......@@ -551,14 +552,16 @@ class Resolver(AbstractResolver):
"""
def __init__(self, hub=None): # pylint: disable=unused-argument
self._resolver = _DualResolver()
if resolver._resolver is None:
resolver._resolver = self._resolver
_resolver = resolver._resolver = _DualResolver()
if config.resolver_nameservers:
self._resolver.network_resolver.nameservers[:] = config.resolver_nameservers
_resolver.network_resolver.nameservers[:] = config.resolver_nameservers
if config.resolver_timeout:
_resolver.network_resolver.lifetime = config.resolver_timeout
# Different hubs in different threads could be sharing the same
# resolver.
assert isinstance(resolver._resolver, _DualResolver)
self._resolver = resolver._resolver
@property
def resolver(self):
......@@ -590,6 +593,8 @@ class Resolver(AbstractResolver):
ans = net_resolver.query(hostname, dns.rdatatype.CNAME, rdtype)
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.resolver.NoNameservers):
break
except dTimeout:
break
else:
aliases.extend(str(rr.target) for rr in ans.rrset)
hostname = ans[0].target
......
from __future__ import absolute_import, print_function
# Best run with dnsmasq configured as a caching nameserver
# with no timeouts and configured to point there via
# /etc/resolv.conf and GEVENTARES_SERVERS=
import gevent.monkey; gevent.monkey.patch_all()
import gevent
import sys
import socket
import time
from zope.dottedname.resolve import resolve as drresolve
blacklist = {22, 55, 68, 69, 99, 120, 130, 152, 161, 165, 169, 172,
199, 205, 239, 235, 254, 256}
RUN_COUNT = 15 if hasattr(sys, 'pypy_version_info') else 5
def quiet(f, n):
try:
f(n)
except socket.gaierror:
pass
def resolve_seq(res, count=10, begin=0):
for index in range(begin, count + begin):
if index in blacklist:
continue
try:
res.gethostbyname('www.x%s.com' % index)
except socket.gaierror:
pass
def resolve_par(res, count=10, begin=0):
gs = []
for index in range(begin, count + begin):
if index in blacklist:
continue
gs.append(gevent.spawn(quiet, res.gethostbyname, 'www.x%s.com' % index) )
gevent.joinall(gs)
def run_all(name, resolve=resolve_par):
count = 100
res = drresolve('gevent.resolver.' + name + '.Resolver')
before = time.time()
resolve(res(), count=count)
after1 = time.time()
resolve(res(), count=count, begin=count)
after2 = time.time()
resolve(res(), count=count, begin=count * 2)
after3 = time.time()
return (name, before, after1, after2, after3)
def make_results():
result_map = {}
names = 'dnspython', 'blocking', 'ares', 'thread'
for name in names:
print("Testing", name)
results = []
for _ in range(RUN_COUNT):
r = run_all(name)
delta = r[-1] - r[1]
print("\t%.2f" % delta, end="")
sys.stdout.flush()
results.append((delta, r))
results.sort()
best = results[0]
print("\n%s: best of %d runs: %.2f; worst: %.2f" % (name, RUN_COUNT, best[0], results[-1][0]))
result_map[name] = best[1]
return [result_map[x] for x in names]
results = make_results()
print('| Resolver | One Iteration | Three Iterations | Delta 3 - two | ')
print('| -------- | ------------: | ----------------:| -------------:|' )
for result in results:
name, before, after1, after2, after3 = result
one_it = after1 - before
two_it = after2 - before
three_it = after3 - before
delta2 = after2 - after1
delta = after3 - after2
print("| %9s | %13.2f | %16.2f | %13.2f |" % (name, one_it, three_it, delta))
"""Benchmarking sleep(0) performance."""
from __future__ import print_function
import sys
from time import time
try:
xrange
except NameError:
xrange = range
def noop(p):
pass
N = 100000
ARG = 0
def test(sleep, arg):
start = time()
for _ in xrange(N):
sleep(arg)
return time() - start
def bench_none():
test(noop)
def bench_gevent(arg=0):
import gevent
from gevent import sleep
delta = test(sleep, arg)
print('gevent %s (%s): sleep(%r): %.1f microseconds' % (gevent.__version__, gevent.__file__, arg, delta * 1000000. / N))
def bench_eventlet(arg):
try:
import eventlet
except ImportError as ex:
sys.stderr.write('Failed to import eventlet: %s\n' % ex)
return
from eventlet.api import sleep
delta = test(sleep, arg)
print('eventlet %s (%s): sleep(%r): %.1f microseconds' % (eventlet.__version__, eventlet.__file__, arg, delta * 1000000. / N))
def main():
global N
for arg in [0, -1, 0.00001]:
bench_gevent(arg)
bench_eventlet(arg)
N = 1000
bench_gevent(0.001)
bench_eventlet(0.001)
if __name__ == '__main__':
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment