Title: Poor thread scaling when constructing instances or accessing attributes · Issue #139103 · python/cpython · GitHub
Open Graph Title: Poor thread scaling when constructing instances or accessing attributes · Issue #139103 · python/cpython
X Title: Poor thread scaling when constructing instances or accessing attributes · Issue #139103 · python/cpython
Description: Bug report Remaining scaling bugs dataclass namedtuple enum Bug description: When constructing dataclass or NamedTuple instances on multiple threads (on a free threading build), or accessing enum class attributes, performance doesn't sca...
Open Graph Description: Bug report Remaining scaling bugs dataclass namedtuple enum Bug description: When constructing dataclass or NamedTuple instances on multiple threads (on a free threading build), or accessing enum c...
X Description: Bug report Remaining scaling bugs dataclass namedtuple enum Bug description: When constructing dataclass or NamedTuple instances on multiple threads (on a free threading build), or accessing enum c...
Opengraph URL: https://github.com/python/cpython/issues/139103
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Poor thread scaling when constructing instances or accessing attributes","articleBody":"# Bug report\n\n### Remaining scaling bugs\n\n- [x] dataclass\n- [x] namedtuple\n- [ ] enum\n\n### Bug description:\n\nWhen constructing dataclass or NamedTuple instances on multiple threads (on a free threading build), or accessing enum class attributes, performance doesn't scale when using multiple threads.\n\nRegular class example (scales well):\n```python\n# b_regular_class.py\nfrom threading import Thread\nfrom time import time\nimport sys\n\nclass Foo:\n def __init__(self, x):\n self.x = x\n\nniter = 5 * 1000 * 1000\n\ndef benchmark(n):\n for i in range(n):\n Foo(x=1)\n\nfor nth in (1, 4):\n t0 = time()\n threads = [Thread(target=benchmark, args=(niter,)) for _ in range(nth)]\n for t in threads:\n t.start()\n for t in threads:\n t.join()\n print(f\"{nth=} {(time() - t0) / nth}\")\n```\n\nDataclass example (doesn't scale well):\n```py\n# b_dataclass.py\nfrom threading import Thread\nfrom dataclasses import dataclass\nfrom time import time\nimport sys\n\n@dataclass\nclass Foo:\n x: int\n\nniter = 5 * 1000 * 1000\n\ndef benchmark(n):\n for i in range(n):\n Foo(x=1)\n\nfor nth in (1, 4):\n t0 = time()\n threads = [Thread(target=benchmark, args=(niter,)) for _ in range(nth)]\n for t in threads:\n t.start()\n for t in threads:\n t.join()\n print(f\"{nth=} {(time() - t0) / nth}\")\n```\n\nNamed tuple example (doesn't scale well):\n```py\n# b_namedtuple.py\nfrom threading import Thread\nfrom typing import NamedTuple\nfrom time import time\nimport sys\n\nclass Foo(NamedTuple):\n x: int\n\nniter = 5 * 1000 * 1000\n\ndef benchmark(n):\n for i in range(n):\n Foo(x=1)\n\nfor nth in (1, 4):\n t0 = time()\n threads = [Thread(target=benchmark, args=(niter,)) for _ in range(nth)]\n for t in threads:\n t.start()\n for t in threads:\n t.join()\n print(f\"{nth=} {(time() - t0) / nth}\")\n```\n\nEnum example (doesn't scale well):\n```py\n# b_enum.py\nfrom threading import Thread\nfrom time import time\nfrom enum import Enum\nimport sys\n\nclass Foo(Enum):\n X = 1\n Y = 2\n\nniter = 5 * 1000 * 1000\n\ndef benchmark(n):\n for i in range(n):\n Foo.X\n Foo.Y.value\n\nfor nth in (1, 4):\n t0 = time()\n threads = [Thread(target=benchmark, args=(niter,)) for _ in range(nth)]\n for t in threads:\n t.start()\n for t in threads:\n t.join()\n print(f\"{nth=} {(time() - t0) / nth}\")\n```\nResults on recent main branch (running on an EC2 instance):\n```\n(cpython-dev) jukka@jukka-coder-dbx free-threading-benchmarks $ py b_regular_class.py\nnth=1 1.1085155010223389\nnth=4 0.2796591520309448\n(cpython-dev) jukka@jukka-coder-dbx free-threading-benchmarks $ py b_dataclass.py\nnth=1 1.1910037994384766\nnth=4 1.0931583642959595\n(cpython-dev) jukka@jukka-coder-dbx free-threading-benchmarks $ py b_namedtuple.py\nnth=1 1.5688557624816895\nnth=4 2.0257126092910767\n(cpython-dev) jukka@jukka-coder-dbx free-threading-benchmarks $ py b_enum.py\nnth=1 0.9439797401428223\nnth=4 2.272495985031128\n```\nThe expected behavior is that when using 4 threads (`nth=4`), the elapsed time per benchmark iteration (the second printed value) goes down significantly compared to when using a single thread (`nth=1`), which happens with the first benchmark (`b_regular_class.py`) but not the others.\n\ncc @colesbury (we discussed this at CPython Core Dev Sprint in person)\n\n### CPython versions tested on:\n\nCPython main branch\n\n### Operating systems tested on:\n\nLinux\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-141596\n* gh-141603\n* gh-141750\n* gh-144332\n* gh-144406\n* gh-144407\n* gh-144977\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/JukkaL","@type":"Person","name":"JukkaL"},"datePublished":"2025-09-18T09:29:23.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":12},"url":"https://github.com/139103/cpython/issues/139103"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:9c22d6ce-a33c-204c-da99-664b065b8fe8 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A5BE:2A9631:273B06:35C54C:6A558F9C |
| html-safe-nonce | 674ce9c0b678307c62eed823e642b7909388b7481dcaf8226e1fc1d0275645d8 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBNUJFOjJBOTYzMToyNzNCMDY6MzVDNTRDOjZBNTU4RjlDIiwidmlzaXRvcl9pZCI6Ijc2NTE5NzA1MzI5ODUxMTQ1MjQiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 269d65591123cbdf318ac766abe390171d1cd6e64539c2f4267f568ee18192b0 |
| hovercard-subject-tag | issue:3429494310 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/139103/issue_layout |
| twitter:image | https://opengraph.githubassets.com/831c3400ab3022ddfbe2de59f2320985a279a9131deedfbfc4e25919c3d643d0/python/cpython/issues/139103 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/831c3400ab3022ddfbe2de59f2320985a279a9131deedfbfc4e25919c3d643d0/python/cpython/issues/139103 |
| og:image:alt | Bug report Remaining scaling bugs dataclass namedtuple enum Bug description: When constructing dataclass or NamedTuple instances on multiple threads (on a free threading build), or accessing enum c... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | JukkaL |
| hostname | github.com |
| expected-hostname | github.com |
| None | b5665c84831ed9ac4fb79519c16c9c5580ba8092fb8bb6e3e72972ec7197348e |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | aa21baa44893467b0b640d0300538f84ca8c475b |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width