Refactor `duration` to store time in seconds

This commit is contained in:
Adam Turner
2023-08-13 19:36:51 +01:00
committed by Adam Turner
parent e010e24728
commit f8e9536344

View File

@@ -1,20 +1,22 @@
"""Measure durations of Sphinx processing."""
"""Measure document reading durations."""
from __future__ import annotations
from datetime import datetime, timedelta
import time
from itertools import islice
from operator import itemgetter
from typing import Any, cast
from docutils import nodes
from typing import TYPE_CHECKING, cast
import sphinx
from sphinx.application import Sphinx
from sphinx.domains import Domain
from sphinx.locale import __
from sphinx.util import logging
if TYPE_CHECKING:
from docutils import nodes
from sphinx.application import Sphinx
logger = logging.getLogger(__name__)
@@ -23,10 +25,10 @@ class DurationDomain(Domain):
name = 'duration'
@property
def reading_durations(self) -> dict[str, timedelta]:
def reading_durations(self) -> dict[str, float]:
return self.data.setdefault('reading_durations', {})
def note_reading_duration(self, duration: timedelta) -> None:
def note_reading_duration(self, duration: float) -> None:
self.reading_durations[self.env.docname] = duration
def clear(self) -> None:
@@ -35,7 +37,7 @@ class DurationDomain(Domain):
def clear_doc(self, docname: str) -> None:
self.reading_durations.pop(docname, None)
def merge_domaindata(self, docnames: list[str], otherdata: dict[str, timedelta]) -> None:
def merge_domaindata(self, docnames: list[str], otherdata: dict[str, float]) -> None:
for docname, duration in otherdata.items():
if docname in docnames:
self.reading_durations[docname] = duration
@@ -44,7 +46,7 @@ class DurationDomain(Domain):
def on_builder_inited(app: Sphinx) -> None:
"""Initialize DurationDomain on bootstrap.
This clears results of last build.
This clears the results of the last build.
"""
domain = cast(DurationDomain, app.env.get_domain('duration'))
domain.clear()
@@ -52,31 +54,31 @@ def on_builder_inited(app: Sphinx) -> None:
def on_source_read(app: Sphinx, docname: str, content: list[str]) -> None:
"""Start to measure reading duration."""
app.env.temp_data['started_at'] = datetime.now()
app.env.temp_data['started_at'] = time.monotonic()
def on_doctree_read(app: Sphinx, doctree: nodes.document) -> None:
"""Record a reading duration."""
started_at = app.env.temp_data['started_at']
duration = datetime.now() - started_at
duration = time.monotonic() - started_at
domain = cast(DurationDomain, app.env.get_domain('duration'))
domain.note_reading_duration(duration)
def on_build_finished(app: Sphinx, error: Exception) -> None:
"""Display duration ranking on current build."""
"""Display duration ranking on the current build."""
domain = cast(DurationDomain, app.env.get_domain('duration'))
durations = sorted(domain.reading_durations.items(), key=itemgetter(1), reverse=True)
if not durations:
if not domain.reading_durations:
return
durations = sorted(domain.reading_durations.items(), key=itemgetter(1), reverse=True)
logger.info('')
logger.info(__('====================== slowest reading durations ======================='))
for docname, d in islice(durations, 5):
logger.info('%d.%03d %s', d.seconds, d.microseconds / 1000, docname)
logger.info(f'{d:.3f} {docname}') # NoQA: G004
def setup(app: Sphinx) -> dict[str, Any]:
def setup(app: Sphinx) -> dict[str, bool | str]:
app.add_domain(DurationDomain)
app.connect('builder-inited', on_builder_inited)
app.connect('source-read', on_source_read)