Skip to content

gh-160788: Fix exponential time in code object comparison - #160849

Open
iliev-blnk wants to merge 1 commit into
python:mainfrom
iliev-blnk:gh-160788-code-eq
Open

iliev-blnk wants to merge 1 commit into
python:mainfrom
iliev-blnk:gh-160788-code-eq

Conversation

@iliev-blnk

@iliev-blnk iliev-blnk commented Oct 28, 2026 •

Copy link
Copy Markdown

code_richcompare() compared _PyCode_ConstantKey(co_consts). For a tuple, that key is the pair (item_keys, tuple), so comparing two keys compares each nested code object twice: once through its item key, which is the code object itself, and once through the original tuple. That doubles the work at every level of nesting.

This compares the keys of the constants one by one instead. The result is the same: equal item keys already imply equal items, so comparing the original tuple again never changed the result.

With the reproducer from the issue on a debug build, depth 20 took 3.0 s on main and depth 30 didn't finish. With this change, depth 30 takes under 1 ms.

Tests:

  • test_code_equality_nested: the 30-deep reproducer. It hangs on main.
  • test_code_equality_uses_consts: checks that the comparison still tells apart 0.0, -0.0, 0, False, (0.0,) and an extra constant. It passes on main and with this change.

code_richcompare() compared the constant key of the whole co_consts
tuple.  The key of a tuple is a pair of the item keys and the tuple
itself, so each nested code object was compared twice per level of
nesting.  Compare the keys of the constants one by one instead.
@python-cla-bot

python-cla-bot Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant