Skip to content

Avoid rescanning long blocks for hash headers and admonitions - #1703

Merged
waylan merged 3 commits into
Python-Markdown:masterfrom
deadstrobe5:perf/hash-header-admonition-guard
Nov 10, 2026
Merged

waylan merged 3 commits into
Python-Markdown:masterfrom
deadstrobe5:perf/hash-header-admonition-guard

Conversation

@deadstrobe5

@deadstrobe5 deadstrobe5 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Description

When a processor takes one line off a block and returns the rest, every block processor tests the rest again. HashHeaderProcessor.test and AdmonitionProcessor.test run a regular expression starting with (?:^|\n) over the whole remainder each time, which is slow because the regex has no literal prefix to search for. Tight headers, tight changelogs and Setext headers with no blank lines between them pay this once per line.

This checks for a line starting with # (or for !!!) with a plain substring test before running the regex. The regex needs that text to match, so the result is the same. SetextHeaderProcessor.run also splits only the first two lines instead of splitting the whole block and joining it back.

Median of 5 alternating runs in one process, CPython 3.14, extensions toc, tables, fenced_code, admonition, attr_list, footnotes, def_list, abbr and md_in_html:

Document Before After
2,000 headers with no blank lines 2436 ms 913 ms
Tight changelog, 500 entries 327 ms 154 ms
1,000 Setext headers with no blank lines 976 ms 251 ms
2 KB page 1.98 ms 1.90 ms

The old and new code give the same HTML on 30,000 generated documents mixing headers, admonitions, tables, lists and other blocks.

AI Assistance Disclosure

  • No AI tools were used in preparing this PR.

  • AI tools were used and I have disclosed which ones, and have fully reviewed and verified their output.

    Claude Code (Claude Opus 5.5) was used for everything ticked below. The review attestation in the box above is left for the human submitter.

    AI tools were use to assist with the following:

    • Code
    • Code Comments
    • Documentation
    • Changelog Entry
    • Commit Message
    • The Description Above
    • Other: ______________

Checklist

@waylan waylan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work on this.

@waylan waylan added the approved The pull request is ready to be merged. label Nov 10, 2026
@waylan
waylan merged commit f368c7d into Python-Markdown:master Nov 10, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved The pull request is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants