diff --git a/doc/benchmarks.rst b/doc/benchmarks.rst index 06104a69..51a9dfd0 100644 --- a/doc/benchmarks.rst +++ b/doc/benchmarks.rst @@ -53,6 +53,18 @@ depending on the Python version. Files are called ``.py.txt`` instead of ``.py`` to not run PEP 8 checks on them, and more generally to not modify them. +alloc +----- + +Allocate blocks of memory with ``bytesarray``. The default sizes are smaller or +equal to obmalloc's small request threshold. + +Command lines options:: + + sizes Block sizes (default: 4 8 16 32 64 128 256 446) + + --repeat REPEAT Repeat allocations (default: 100) + chameleon --------- diff --git a/pyperformance/data-files/benchmarks/MANIFEST b/pyperformance/data-files/benchmarks/MANIFEST index a52cb7a1..a5fe201b 100644 --- a/pyperformance/data-files/benchmarks/MANIFEST +++ b/pyperformance/data-files/benchmarks/MANIFEST @@ -2,6 +2,7 @@ name metafile 2to3 +alloc chameleon chaos crypto_pyaes diff --git a/pyperformance/data-files/benchmarks/bm_alloc/pyproject.toml b/pyperformance/data-files/benchmarks/bm_alloc/pyproject.toml new file mode 100644 index 00000000..01a5f3f4 --- /dev/null +++ b/pyperformance/data-files/benchmarks/bm_alloc/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "pyperformance_bm_alloc" +requires-python = ">=3.8" +dependencies = ["pyperf"] +urls = {repository = "https://github.com/python/pyperformance"} +dynamic = ["version"] + +[tool.pyperformance] +name = "alloc" +tags = "micro" diff --git a/pyperformance/data-files/benchmarks/bm_alloc/run_benchmark.py b/pyperformance/data-files/benchmarks/bm_alloc/run_benchmark.py new file mode 100644 index 00000000..4cdaa041 --- /dev/null +++ b/pyperformance/data-files/benchmarks/bm_alloc/run_benchmark.py @@ -0,0 +1,73 @@ +# coding: utf-8 +""" +Allocate blocks of memory with bytearray + +This benchmark stresses the memory allocator. Default sizes are <= +obmalloc's small request threshold. +""" + +import sys + +import pyperf + +# see Objects/obmalloc.c +SMALL_REQUEST_THRESHOLD = 512 +APPEND_SIZE = 10 +SIZEOF_BYTEARRAY = sys.getsizeof(bytearray()) + +REPEAT_ALLOCS = 100 + +DEFAULT_SIZES = [ + 4, + 8, + 16, + 32, + 64, + 128, + 256, + # keep below obmalloc threshold + SMALL_REQUEST_THRESHOLD - SIZEOF_BYTEARRAY - APPEND_SIZE, +] + + +def allocate(repeat, sizes, alloc_func=bytearray): + append = alloc_func(APPEND_SIZE) + for size in sizes: + append = alloc_func(size) + for i in range(repeat): + # malloc() + block = alloc_func(size) + # realloc() + block += append + # free() + del block + + +def add_cmdline_args(cmd, args): + cmd.extend(("--repeat", str(args.repeat))) + cmd.extend(tuple(str(s) for s in args.sizes)) + + +if __name__ == "__main__": + runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) + + cmd = runner.argparser + cmd.add_argument( + "--repeat", + type=int, + default=REPEAT_ALLOCS, + help=f"Repeat allocations (default: {REPEAT_ALLOCS})", + ) + cmd.add_argument( + "sizes", + type=int, + nargs="*", + default=DEFAULT_SIZES, + help=f"Block sizes (default: {' '.join(str(s) for s in DEFAULT_SIZES)})", + ) + + args = runner.parse_args() + runner.metadata["description"] = "Allocate blocks of memory." + runner.metadata["alloc_repeat"] = args.repeat + runner.metadata["alloc_sizes"] = ",".join(str(s) for s in args.sizes) + runner.bench_func("alloc", allocate, args.repeat, args.sizes)