Skip to main content

[WIP] sphinx-benchmark

This is a Sphinx extension that benchmarks and profiles a docs build process event-wise(handler-wise), and the gaps in between the events-- so you can tell which extension, theme, or part of Sphinx itself is slowing your builds.

You can find the benchmarking outputs for different Scientific Python projects and learn more about the benchmarking output in the benchmarking_outputs directory.

Usage

  1. Add the extension to your conf.py:

    extensions = ["sphinx_benchmark", ...]
    

    Put it first in the list as it minimizes (but doesn't eliminate) the untracked starting time.

  2. Then build your docs as usual:

    sphinx-build -b html docs/ docs/_build/html
    

    The build generates a sphinx_benchmarks.json in the present working directory.

  3. Run the print_summary.py script to get the benchmarking output:

    python path/to/sphinx-benchmark/src/sphinx_benchmark/print_summary.py
    

    For what the output actually mean, see the benchmarking_outputs README.

How are benchmarks calculated?

Nearly everything an extension does in Sphinx goes through app.events.emit(). Sphinx calls it at certain points in the build process, and it runs all the registered handler for that event. This extension wraps and puts timers around this path.

wrap_emit() wraps app.events.emit that times the whole emission, and wrap_listener() swaps each handler for a wrapped and timed copy of it. So for every event you get the total time it took and the split across its handlers. A stack is maintained to keep track of nested event, and the child event's time is later subtracted so it isn't counted twice. wrap_all_listeners() wraps everything already registered when the extension loads, and wrap_connect() wraps app.events.connect so handlers and events registered later, also get wrapped as they are called.

Each timed call becomes a HandlerCall record and each event emission becomes an Event record, both kept in one EventLogger. All times are measured from the moment the extension started, so everything shares a starting point.

At build-finished (at priority 999, so other extensions' handlers gets executed first) the extension works out each event's own time, classify every handler with where it came from, and dumps everything into a JSON.

Limitations of this extension - WIP

  • No parallel builds: The recorder lives in the main process only, so parallel_read_safe and parallel_write_safe are both False. Sphinx will fall back to a serial build even if you pass -j auto, which means the wall-clock total won't match what you'd normally see, when you are building with parallelism.
  • The build-finished emission has duration=None. The handler that writes the JSON runs inside that emission, so the emission hasn't ended yet when it's serialised. It's stored with duration=None and the summary skips it. Anything after it, like builder.cleanup() isn't measured at all.
  • The startup blind spot: Timing begins at the extension's setup(). The "startup, before first emission" row in the gaps table covers only what happened after that point.
  • Some handlers can't be classified: Handlers defined in conf.py, or in a package that doesn't match anything in app.extensions, are classified as unknown and reported by module or file name. Partials and callable objects have no __qualname__, so they're labelled by whatever name could be recovered.
  • the extension itself also adds a little bit of overhead to the build process.
  • Wall clock time is not CPU time: caches, background processes, and network fetches all are included in the total time. Run benchmarks more than once before concluding anything.

Thank you for stopping by :)

Release files for sphinx-benchmark 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sphinx-benchmark 0.1.0
File Size Uploaded
sphinx_benchmark-0.1.0.tar.gz 36.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sphinx-benchmark 0.1.0
File Interpreter ABI Platform
sphinx_benchmark-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 48.7 kB

Release files / sphinx_benchmark-0.1.0.tar.gz

Download URL sphinx_benchmark-0.1.0.tar.gz
Size 36.8 kB
Tags Source
SHA-256 checksum
How to use checksums
57df7d6c353748883cdc6521e978f33b01fb3b6fc6787f89aa1e183aaf5c864f
BLAKE2b-256 checksum
How to use checksums
3248377d61fe48d9f771abdb462626a4e0b701fdcd8d3c0b07690f0318215273
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.18.0 {"ci":null,"cpu":"arm64","distro":{"name":"macOS","version":"26.3.1"},"implementation":{"name":"CPython","version":"3.12.13"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.6.1 27 Jan 2026","python":"3.12.13","system":{"name":"Darwin","release":"25.3.0"}} HTTPX2/2.12.0

Release files / sphinx_benchmark-0.1.0-py3-none-any.whl

Download URL sphinx_benchmark-0.1.0-py3-none-any.whl
Size 11.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c185ccecea40551252659ed166c9523e06922b6955d0bbe6b71238d58a37e96f
BLAKE2b-256 checksum
How to use checksums
e726b564c40758b7afb93b40228d6eb84dac7dcf9d5b1e2ad99f4675c5c1a08f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.18.0 {"ci":null,"cpu":"arm64","distro":{"name":"macOS","version":"26.3.1"},"implementation":{"name":"CPython","version":"3.12.13"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.6.1 27 Jan 2026","python":"3.12.13","system":{"name":"Darwin","release":"25.3.0"}} HTTPX2/2.12.0

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page