Skip to content

gh-158525: Avoid reacquiring dict lock when copying - #158535

Open
n1snt wants to merge 1 commit into
python:mainfrom
n1snt:gh-158525-sparse-dict-copy
Open

n1snt wants to merge 1 commit into
python:mainfrom
n1snt:gh-158525-sparse-dict-copy

Conversation

@n1snt

@n1snt n1snt commented Sep 30, 2026 •

Copy link
Copy Markdown

When copying a sparse mutable dict, PyDict_Copy() already holds the source lock. The compaction fallback called dict_merge(), which tried to acquire the source again as part of a two-object critical section. In a free-threaded build, this caused the thread to spin and park on its own lock.

Call dict_dict_merge() directly when the source uses the built-in iterator. The destination is newly created and not visible to other threads. Keep the generic merge path for frozendicts and subclasses with custom iteration.

The existing test_copy_noncompact test covers the changed copy path.

Benchmark

Linux arm64, free-threaded current main release build:

Operation Before After
compact.copy() 0.108 us 0.108 us
sparse.copy() 9.86 us 0.169 us
dict(sparse) 0.178 us 0.173 us

Tests

  • Free-threaded debug build: ./python -m test -v test_dict test_free_threading.test_dict
  • GIL-enabled debug build: ./python -m test -v test_dict

AI use: I used an AI assistant to help inspect the locking path and prepare the change. I reviewed the diff and ran the tests and benchmarks above.

Fixes #158525

@python-cla-bot

python-cla-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

@n1snt
n1snt force-pushed the gh-158525-sparse-dict-copy branch from 6f571fa to dc3a363 Compare September 30, 2026 22:26
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.

Free-threaded dict.copy() spins on an already-held source lock when compacting a sparse dict

1 participant