Skip to content

Commit

Permalink
Get the spawn benchmark working again [skip ci]
Browse files Browse the repository at this point in the history
Current results:

| Benchmark             | gevent-libev-cext | gevent-libev-cffi             | gevent-libuv-cffi               |
|-----------------------|-------------------|-------------------------------|---------------------------------|
| gevent spawn          | 12.5 us           | 13.7 us: 1.10x slower (+10%)  | 14.2 us: 1.14x slower (+14%)    |
| gevent sleep          | 2.09 us           | 3.16 us: 1.51x slower (+51%)  | 74.4 us: 35.64x slower (+3464%) |
| geventpool sleep      | 3.46 us           | 6.20 us: 1.79x slower (+79%)  | 151 us: 43.58x slower (+4258%)  |
| geventraw spawn       | 5.34 us           | 6.54 us: 1.22x slower (+22%)  | 6.38 us: 1.19x slower (+19%)    |
| geventraw sleep       | 949 ns            | 1.66 us: 1.75x slower (+75%)  | 43.9 us: 46.25x slower (+4525%) |
| geventpool join       | 1.57 us           | 3.43 us: 2.18x slower (+118%) | 88.2 us: 56.07x slower (+5507%) |
| gevent spawn kwarg    | 14.2 us           | 12.4 us: 1.15x faster (-13%)  | 14.8 us: 1.04x slower (+4%)     |
| geventraw spawn kwarg | 7.68 us           | 8.38 us: 1.09x slower (+9%)   | 8.47 us: 1.10x slower (+10%)    |
| none spawn kwarg      | 771 ns            | 738 ns: 1.04x faster (-4%)    | 734 ns: 1.05x faster (-5%)      |

Not significant (3): geventpool spawn; none spawn; geventpool spawn kwarg

Refs #1493
  • Loading branch information
jamadden committed Dec 17, 2019
1 parent aae6b46 commit 3c453c7
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 35 deletions.
98 changes: 64 additions & 34 deletions benchmarks/bench_spawn.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
"""Benchmarking spawn() performance.
"""
from __future__ import print_function, absolute_import, division
Benchmarking spawn() performance.
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division

import perf
from pyperf import perf_counter
from pyperf import Runner

try:
xrange
Expand All @@ -14,7 +18,7 @@
counter = 0


def incr(sleep, **_kwargs):
def incr(**_kwargs):
global counter
counter += 1

Expand Down Expand Up @@ -48,35 +52,38 @@ def __init__(self,
def _test(spawn, sleep, options):
global counter
counter = 0
before_spawn = perf.perf_counter()
before_spawn = perf_counter()
for _ in xrange(N):
spawn(incr, sleep, **options.kwargs)
spawn(incr, **options.kwargs)
spawn_duration = perf_counter() - before_spawn


before_sleep = perf.perf_counter()
if options.sleep:
assert counter == 0, counter
before_sleep = perf_counter()
sleep(0)
after_sleep = perf.perf_counter()
sleep_duration = perf_counter() - before_sleep
assert counter == N, (counter, N)
else:
after_sleep = before_sleep
sleep_duration = -1


if options.join:
before_join = perf.perf_counter()
before_join = perf_counter()
options.join()
after_join = perf.perf_counter()
join_duration = after_join - before_join
join_duration = perf_counter() - before_join
else:
join_duration = -1

return Times(before_sleep - before_spawn,
after_sleep - before_sleep,
return Times(spawn_duration,
sleep_duration,
join_duration)

def test(spawn, sleep, options):
all_times = [_test(spawn, sleep, options)
for _ in xrange(options.loops)]
all_times = [
_test(spawn, sleep, options)
for _ in xrange(options.loops)
]

spawn_duration = sum(x.spawn_duration for x in all_times)
sleep_duration = sum(x.sleep_duration for x in all_times)
Expand All @@ -86,17 +93,20 @@ def test(spawn, sleep, options):
return Times(spawn_duration, sleep_duration, join_duration)

def bench_none(options):
options.sleep = False
def spawn(f, sleep, **kwargs):
return f(sleep, **kwargs)
from time import sleep

options.sleep = False

def spawn(f, **kwargs):
return f(**kwargs)

return test(spawn,
sleep,
options)


def bench_gevent(options):
from gevent import spawn, sleep
from gevent import spawn, sleep, get_hub
return test(spawn, sleep, options)


Expand All @@ -115,13 +125,17 @@ def bench_geventpool(options):
return times



def bench_eventlet(options):
from eventlet import spawn, sleep
from eventlet.hubs import use_hub
if options.eventlet_hub is not None:
use_hub(options.eventlet_hub)
return test(spawn, sleep, options)
try:
__import__('eventlet')
except ImportError:
pass
else:
def bench_eventlet(options):
from eventlet import spawn, sleep
if options.eventlet_hub is not None:
from eventlet.hubs import use_hub
use_hub(options.eventlet_hub)
return test(spawn, sleep, options)


def all():
Expand All @@ -132,11 +146,27 @@ def all():



def main():
def main(argv=None):
import os
import sys
if argv is None:
argv = sys.argv[1:]

env_options = [
'--inherit-environ',
','.join([k for k in os.environ
if k.startswith(('GEVENT',
'PYTHON',
'ZS', # experimental zodbshootout config
'RS', # relstorage config
'COVERAGE'))])]
# This is a default, so put it early
argv[0:0] = env_options

def worker_cmd(cmd, args):
cmd.extend(args.benchmark)

runner = perf.Runner(add_cmdline_args=worker_cmd)
runner = Runner(add_cmdline_args=worker_cmd)
runner.argparser.add_argument('benchmark',
nargs='*',
default='all',
Expand All @@ -157,7 +187,7 @@ def join_time(loops, func, options):
times = func(options)
return times.join_duration

args = runner.parse_args()
args = runner.parse_args(argv)

if 'all' in args.benchmark or args.benchmark == 'all':
args.benchmark = ['all']
Expand All @@ -171,28 +201,28 @@ def join_time(loops, func, options):
runner.bench_time_func(name + ' spawn',
spawn_time,
globals()['bench_' + name],
Options(False, False),
Options(sleep=False, join=False),
inner_loops=N)

if name != 'none':
runner.bench_time_func(name + ' sleep',
sleep_time,
globals()['bench_' + name],
Options(True, False),
Options(sleep=True, join=False),
inner_loops=N)

if 'geventpool' in names:
runner.bench_time_func('geventpool join',
join_time,
bench_geventpool,
Options(True, True),
Options(sleep=True, join=True),
inner_loops=N)

for name in names:
runner.bench_time_func(name + ' spawn kwarg',
spawn_time,
globals()['bench_' + name],
Options(False, False, foo=1, bar='hello'),
Options(sleep=False, join=False, foo=1, bar='hello'),
inner_loops=N)

if __name__ == '__main__':
Expand Down
7 changes: 6 additions & 1 deletion src/gevent/_ffi/loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,12 @@ def update(self):
self.update_now()

def __repr__(self):
return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), self._format())
return '<%s.%s at 0x%x %s>' % (
self.__class__.__module__,
self.__class__.__name__,
id(self),
self._format()
)

@property
def default(self):
Expand Down

0 comments on commit 3c453c7

Please sign in to comment.