Skip to content

Avoid cubic time for comments inside open inline tags - #1684

Open
naaz234 wants to merge 1 commit into
Python-Markdown:masterfrom
naaz234:inline-comment-endtag-scan
Open

naaz234 wants to merge 1 commit into
Python-Markdown:masterfrom
naaz234:inline-comment-endtag-scan

Conversation

@naaz234

@naaz234 naaz234 commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Description

HTMLExtractor.inline_close_follows (added for #1643) runs on every comment while a raw inline tag is open. Each call copies the rest of the paragraph and runs one regex per entry of inline_stack over it, so n open tags followed by n comments is cubic:

'x ' + '<span>' * 500  + '<!---->' * 500     6.5 KB    1.6 s
'x ' + '<span>' * 1000 + '<!---->' * 1000     13 KB   12.3 s
'x ' + '<span>' * 2000 + '<!---->' * 2000     26 KB   75.4 s

The end tags of the paragraph are now found once, with the position of the last end tag of each name. The parser also counts how many times each name is in inline_stack and how many open names still have an end tag ahead. A later comment in the same paragraph only drops the names whose last end tag it has passed. The 26 KB input now takes 0.035 s and 416 KB takes 3.5 s, which is what master already spends on a paragraph of plain <!----> comments of the same size. Mixing tag names, putting a non-matching end tag at the end, or alternating <span><!----> all stay linear too.

Output matches master on 60,000 random documents built from inline/block tags, end tags (including </ span>, </B >, </span/>), comments, blank lines and Markdown syntax, with no extensions, md_in_html and extra. The new test takes over 60 s on master and 0.14 s with this change.

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.

    AI tools were use to assist with the following:

    • Code
    • Code Comments
    • Documentation
    • Changelog Entry
    • Commit Message
    • The Description Above
    • Other: the regression test, the benchmark and the random-document comparison against master

Checklist

@waylan waylan added the needs-review Needs to be reviewed and/or approved. label Oct 29, 2026
Comment thread docs/changelog.md Outdated
characters is followed by more text on the same line.
* Fix quadratic time when a document contains many unclosed HTML comments (`<!--`
with no matching `-->`).
* Fix cubic time when a paragraph contains many HTML comments inside many

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.

We have done a release since this PR was submitted. This edit to the changelog needs to be moved to the new unreleased section.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved it to the end of the new Unreleased section. I rebased onto current master to do it, since the entry had ended up under 3.11.3 after the release, so the diff should only touch the Unreleased list now.

@waylan waylan added requires-changes Awaiting updates after a review. and removed needs-review Needs to be reviewed and/or approved. labels Nov 9, 2026
`HTMLExtractor.inline_close_follows` decides whether a comment inside raw
inline HTML stays in the paragraph by copying the rest of the paragraph
and running one regex per entry of `inline_stack` over it. Every comment
repeats this, so n open inline tags followed by n comments cost O(n^3):
`'x ' + '<span>' * 2000 + '<!---->' * 2000` (26 KB) takes about 75
seconds to convert.

The end tags of a paragraph are now found once, recording the position
of the last end tag of each name. The parser counts how many times each
name is in `inline_stack` and how many open names still have an end tag
ahead. A later comment in the same paragraph only drops the names whose
last end tag it has passed, so each comment no longer depends on the
size of the stack or the length of the paragraph. Output is unchanged.
@naaz234
naaz234 force-pushed the inline-comment-endtag-scan branch from ac331af to f4e3457 Compare November 13, 2026 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-changes Awaiting updates after a review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants