Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bench_async_func() #124

Merged
merged 7 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ Runner class
Methods to run benchmarks:

* :meth:`bench_func`
* :meth:`bench_async_func`
* :meth:`timeit`
* :meth:`bench_command`
* :meth:`bench_time_func`
Expand Down Expand Up @@ -538,6 +539,21 @@ Runner class

See the :ref:`bench_func() example <bench_func_example>`.

.. method:: bench_async_func(name, func, \*args, inner_loops=None, metadata=None)

Benchmark the function ``await func(*args)`` in asyncio event loop.
vstinner marked this conversation as resolved.
Show resolved Hide resolved

*name* is the benchmark name, it must be unique in the same script.

The *inner_loops* parameter is used to normalize timing per loop
iteration.

To call ``func()`` with keyword arguments, use ``functools.partial``.

Return a :class:`Benchmark` instance.

See the :ref:`bench_async_func() example <bench_async_func_example>`.

.. method:: timeit(name, stmt=None, setup="pass", teardown="pass", inner_loops=None, duplicate=None, metadata=None, globals=None)

Run a benchmark on ``timeit.Timer(stmt, setup, globals=globals)``.
Expand Down
10 changes: 10 additions & 0 deletions doc/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ measure the time elapsed when sleeping 1 ms:
``time.sleep()`` is used to simulate a real workload taking at least 1 ms.


.. _bench_async_func_example:

bench_async_func() method
-------------------------

.. literalinclude:: examples/bench_async_func.py

``asyncio.sleep()`` is used to simulate a real workload taking at least 1 ms.


.. _timeit_example:

timeit() method
Expand Down
11 changes: 11 additions & 0 deletions doc/examples/bench_async_func.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env python3
vstinner marked this conversation as resolved.
Show resolved Hide resolved
import asyncio
import pyperf


async def func():
await asyncio.sleep(0.001)


runner = pyperf.Runner()
runner.bench_async_func('async_sleep', func)
55 changes: 55 additions & 0 deletions pyperf/_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,61 @@ def task_func(task, loops):
task.inner_loops = inner_loops
return self._main(task)

def bench_async_func(self, name, func, *args, **kwargs):
"""Benchmark await func(*args)"""

inner_loops = kwargs.pop('inner_loops', None)
metadata = kwargs.pop('metadata', None)
self._no_keyword_argument(kwargs)

if not self._check_worker_task():
return None

if args:
func = functools.partial(func, *args)

def task_func(task, loops):
if loops != 1:
async def main():
# use fast local variables
local_timer = time.perf_counter
local_func = func
range_it = range(loops)

t0 = local_timer()
for _ in range_it:
await local_func()
dt = local_timer() - t0
return dt
else:
async def main():
# use fast local variables
local_timer = time.perf_counter
local_func = func

t0 = local_timer()
await local_func()
dt = local_timer() - t0
return dt

import asyncio
if hasattr(asyncio, 'run'): # Python 3.7+
dt = asyncio.run(main())
else: # Python 3.6
loop = asyncio.new_event_loop()
vstinner marked this conversation as resolved.
Show resolved Hide resolved
asyncio.set_event_loop(loop)
try:
dt = loop.run_until_complete(main())
finally:
asyncio.set_event_loop(None)
loop.close()
vstinner marked this conversation as resolved.
Show resolved Hide resolved

return dt

task = WorkerProcessTask(self, name, task_func, metadata)
task.inner_loops = inner_loops
return self._main(task)
vstinner marked this conversation as resolved.
Show resolved Hide resolved

def timeit(self, name, stmt=None, setup="pass", teardown="pass",
inner_loops=None, duplicate=None, metadata=None, globals=None):

Expand Down
6 changes: 6 additions & 0 deletions pyperf/tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ def test_bench_func_no_warmup(self):
args = ['-p2', '-w0', '--min-time=0.001']
self.check_command(script, args)

def test_bench_async_func(self):
script = 'bench_async_func.py'
# Use -w1 --min-time=0.001 to reduce the duration of the test
args = ['-p2', '-w1', '--min-time=0.001']
self.check_command(script, args)

def test_bench_time_func(self):
script = 'bench_time_func.py'
args = ['-p2', '-w1', '--min-time=0.001']
Expand Down