GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-146558: optimize dict access with objects with known hash by kumaraditya303 · Pull Request #146559 · python/cpython

Conversation

@kumaraditya303

@kumaraditya303 kumaraditya303 commented Mar 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

I asked Claude to create a benchmark for this, it created the following script which shows a real significant speedup.

Benchmark No JIT JIT Speedup
dict_get[str] 55.7M/s 70.1M/s +26%
dict_get[int] 55.5M/s 75.4M/s +36%
dict_get[float] 50.9M/s 74.7M/s +47%
dict_get[complex] 44.9M/s 74.9M/s +67%
dict_store[str] 74.9M/s 85.7M/s +14%
dict_store[int] 76.0M/s 94.1M/s +24%
dict_store[float] 66.6M/s 97.0M/s +46%
dict_store[complex] 55.9M/s 98.0M/s +75%
dict_get[multi] 23.4M/s 35.1M/s +50%
dict_get[obj] 52.9M/s 68.8M/s +30%
dict_store[obj] 75.4M/s 92.5M/s +23%
Details
"""Benchmark dict get/store with constant keys to measure
_BINARY_OP_SUBSCR_DICT_KNOWN_HASH and _STORE_SUBSCR_DICT_KNOWN_HASH speedup.

Usage:
  PYTHON_JIT=0 ./python.exe bench_dict_known_hash.py
  PYTHON_JIT=1 ./python.exe bench_dict_known_hash.py
"""

import time
import os
import sys

N = 50_000_000


def bench_get_str(n):
    d = {'a': 1, 'b': 2, 'c': 3}
    x = 0
    for _ in range(n):
        x += d['a']
    return x


def bench_get_int(n):
    d = {1: 10, 2: 20, 3: 30}
    x = 0
    for _ in range(n):
        x += d[1]
    return x


def bench_store_str(n):
    d = {}
    for _ in range(n):
        d['a'] = 1
    return d


def bench_store_int(n):
    d = {}
    for _ in range(n):
        d[1] = 1
    return d


def bench_get_float(n):
    d = {1.5: 1, 2.5: 2, 3.5: 3}
    x = 0
    for _ in range(n):
        x += d[1.5]
    return x


def bench_store_float(n):
    d = {}
    for _ in range(n):
        d[1.5] = 1
    return d


def bench_get_complex(n):
    d = {1+2j: 1, 3+4j: 2}
    x = 0
    for _ in range(n):
        x += d[1+2j]
    return x


def bench_store_complex(n):
    d = {}
    for _ in range(n):
        d[1+2j] = 1
    return d


def bench_get_multi(n):
    d = {'a': 1, 1: 2, b'x': 3, (1, 2): 4}
    x = 0
    for _ in range(n):
        x += d['a'] + d[1] + d[b'x'] + d[(1, 2)]
    return x


class _Key:
    pass

_KEY = _Key()


def bench_get_obj(n):
    d = {_KEY: 1}
    x = 0
    for _ in range(n):
        x += d[_KEY]
    return x


def bench_store_obj(n):
    d = {}
    for _ in range(n):
        d[_KEY] = 1
    return d


def run_avg(name, func, n, runs=3):
    func(1000)  # warmup
    times = []
    for _ in range(runs):
        t0 = time.perf_counter()
        func(n)
        times.append(time.perf_counter() - t0)
    avg = sum(times) / len(times)
    rate = n / avg / 1e6
    print(f"  {name:25s}  {avg:.3f}s  ({rate:.1f}M iter/s)")
    return avg


if __name__ == "__main__":
    jit = "JIT" if os.environ.get("PYTHON_JIT", "1") == "1" else "no JIT"
    print(f"Python {sys.version.split()[0]} ({jit}), avg of 3 runs\n")

    run_avg("dict_get[str]",      bench_get_str,      N)
    run_avg("dict_get[int]",      bench_get_int,      N)
    run_avg("dict_get[float]",    bench_get_float,    N)
    run_avg("dict_get[complex]",  bench_get_complex,  N)
    run_avg("dict_store[str]",    bench_store_str,    N)
    run_avg("dict_store[int]",    bench_store_int,    N)
    run_avg("dict_store[float]",  bench_store_float,  N)
    run_avg("dict_store[complex]",bench_store_complex,N)
    run_avg("dict_get[multi]",    bench_get_multi,    N // 4)
    run_avg("dict_get[obj]",      bench_get_obj,      N)
    run_avg("dict_store[obj]",    bench_store_obj,    N)
  • Issue: JIT optimize dict access with consts with known hash #146558

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@kumaraditya303
optimize dict access with objects with safe hash
b441e1b
@kumaraditya303
kumaraditya303 requested review from Fidget-Spinner, markshannon, methane, savannahostrowski and tomasr8 as code owners March 28, 2026 09:16
@bedevere-app bedevere-app Bot added the awaiting core review label Mar 28, 2026
@bedevere-app bedevere-app Bot mentioned this pull request Mar 28, 2026
JIT optimize dict access with consts with known hash #146558
Closed
@kumaraditya303 kumaraditya303 added the skip news label Mar 28, 2026
kumaraditya303 added 6 commits March 28, 2026 14:53
@kumaraditya303
fix build on windows
a5b4476
@kumaraditya303
remove benchmark
3263498
@kumaraditya303
improve comments
3af5968
@kumaraditya303
run regen
7707961
@kumaraditya303
fix test warning
2d1a169
@kumaraditya303
optimize floats and complex as well
ea4ae79
Fidget-Spinner
Fidget-Spinner reviewed Mar 30, 2026
View reviewed changes
Comment thread Python/optimizer_bytecodes.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@kumaraditya303
refactor common code to optimize_dict_known_hash
7a4d046
Fidget-Spinner
Fidget-Spinner approved these changes Mar 30, 2026
View reviewed changes
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels Mar 30, 2026
@kumaraditya303
kumaraditya303 enabled auto-merge (squash) March 30, 2026 13:41
@kumaraditya303
kumaraditya303 disabled auto-merge March 30, 2026 13:41
@kumaraditya303
kumaraditya303 enabled auto-merge (squash) March 30, 2026 13:41
@kumaraditya303
kumaraditya303 merged commit 8e9d21c into python:main Mar 30, 2026
117 of 119 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@kumaraditya303
kumaraditya303 deleted the jit-hash branch March 30, 2026 14:23
@bedevere-app bedevere-app Bot removed the awaiting merge label Mar 30, 2026
maurycy added a commit to maurycy/cpython that referenced this pull request Mar 30, 2026
@maurycy
Merge remote-tracking branch 'upstream/main' into tachyon-ndjson-kole…
6a0ea81
…ktor

* upstream/main: (119 commits)
  pythongh-144270: Make SubElement parent and tag positional-only (pythonGH-144845)
  pythongh-146558: JIT optimize dict access for objects with known hash (python#146559)
  pythongh-139922: always run MSVC 64-bit tail-calling CI (pythonGH-146570)
  pythongh-126835: Fix _PY_IS_SMALL_INT() macro (python#146631)
  pythongh-146587: fix type slot assignment incase of multiple slots for same name (python#146593)
  pythongh-138122: Add differential flame graph (python#145785)
  pythongh-146416: Emscripten: Improve standard stream handling in node_entry.mjs (python#146417)
  pythongh-146444: Don't package as part of iOS 'build hosts' target (python#146628)
  pythongh-138850: Add --disable-epoll to configure (pythonGH-145768)
  pythongh-146444: Make Platforms/Apple/ compatible with Python 3.9 (python#146624)
  pythongh-138577: Fix keyboard shortcuts in getpass with echo_char (python#141597)
  pythongh-146556: Fix infinite loop in annotationlib.get_annotations() on circular __wrapped__ (python#146557)
  pythongh-146579: _zstd: Fix decompression options dict error message (python#146577)
  pythongh-146083: Upgrade bundled Expat to 2.7.5 (python#146085)
  pythongh-146080: fix a crash in SNI callbacks when the SSL object is gone (python#146573)
  pythongh-146090: fix memory management of internal `sqlite3` callback contexts (python#146569)
  pythongh-145876: Do not mask KeyErrors raised during dictionary unpacking in call (pythonGH-146472)
  pythongh-146004: fix test_args_from_interpreter_flags on windows (python#146580)
  pythongh-139003: Use frozenset for module level attributes in _pyrepl.utils (python#139004)
  pythonGH-146527: Add more data to GC statistics and add it to PyDebugOffsets (python#146532)
  ...
@kumaraditya303 kumaraditya303 added the topic-JIT label Mar 31, 2026
@pablogsal pablogsal mentioned this pull request Apr 4, 2026
gh-130273: Fix traceback color output with unicode characters #142529
Merged
@Siyet Siyet mentioned this pull request Apr 12, 2026
General optimisations for dict lookup/insert performance #145179
Open
clin1234 pushed a commit to clin1234/cpython that referenced this pull request Apr 16, 2026
@kumaraditya303 @clin1234
pythongh-146558: JIT optimize dict access for objects with known hash (…
96c37e7
…python#146559)
ljfp pushed a commit to ljfp/cpython that referenced this pull request Apr 25, 2026
@kumaraditya303 @ljfp
pythongh-146558: JIT optimize dict access for objects with known hash (…
c8eb289
…python#146559)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@Fidget-Spinner Fidget-Spinner Fidget-Spinner approved these changes
@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner
@tomasr8 tomasr8 Awaiting requested review from tomasr8 tomasr8 is a code owner
@savannahostrowski savannahostrowski Awaiting requested review from savannahostrowski
@methane methane Awaiting requested review from methane methane is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

skip news topic-JIT

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@kumaraditya303 @Fidget-Spinner
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.