| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
|
@rashes2006 Do you have any benchmarks showing the performance gain from these changes? |
Sorry, something went wrong.
|
Also don't update the branch if nothing needs to be updated: https://devguide.python.org/getting-started/pull-request-lifecycle/#update-branch-button. |
Sorry, something went wrong.
|
Tested on CPython 3.15.0a0 (macOS arm64) Test Case: for _ in d.items(): pass
By switching from the variadic PyTuple_Pack to the array-based |
Sorry, something went wrong.
|
Please show us the benchmark script itself as well. Is it on a PGO+LTO build? |
Sorry, something went wrong.
|
@picnixz The benchmarks were run on a standard development build of CPython, not a PGO+LTO build. While PGO+LTO may change absolute timings, the relative speedup is expected to be similar, since the improvement comes from reducing per-iteration C call overhead rather than from whole-program optimizations. |
Sorry, something went wrong.
|
Benchmarks on DEBUG builds are not relevant to us. Please do so on a PGO+LTO. There can be lots of changes between them, especially since the functions being invoked are different and because users won't have a DEBUG build. |
Sorry, something went wrong.
|
Also, we need to see the stdev and the geometric mean. Look at #140010 for how we want benchmarks to be reported. |
Sorry, something went wrong.
Benchmarks (PGO+LTO)All performance results below were collected on a full PGO+LTO build of Platform
Benchmark Scriptimport timeit
import sys
def run_benchmark(setup_stmt, run_stmt, label):
n = 5_000_000
t = timeit.Timer(run_stmt, setup=setup_stmt)
results = t.repeat(repeat=5, number=n)
best = min(results) / n
print(f"{label:10} | Best of 5: {best * 1e9:6.2f} nsec per loop")
if __name__ == "__main__":
print(f"Python Build: {sys.version}")
run_benchmark("d = {0:0}", "for _ in d.items(): pass", "Size 1")
run_benchmark("d = {i: i for i in range(10)}", "for _ in d.items(): pass", "Size 10")##Result
|
Sorry, something went wrong.
|
Can you use pyperf instead of custom benchmarks? It doesn't make sense to only take the smallest time. In addition, I'm still lacking the stdev. And I don't understand the d.items() ^ d.items() thing when the benchmark is something different. Have you generated the script using an LLM? if you did, we won't accept the PR unless it's been correctly proven. |
Sorry, something went wrong.
|
Please pay attention to review comments: "Also, we need to see the stdev and the geometric mean." I suggest you using pyperf instead of reinventing own poor framework for benchmarking. |
Sorry, something went wrong.
|
The benchmark was rewritten to use pyperf idiomatically via runner.timeit(), ensuring proper warmup, calibration, and statistical reporting. The new cases cover baseline iteration, allocation-heavy iteration, and d.items() ^ d.items() to specifically stress tuple creation in dict.items(). The methodology now follows standard CPython benchmarking practices. |
Sorry, something went wrong.
It was not. You seem to use an LLM, and I don't have the time to engage with someone who doesn't want to consider our time. I will close the PR and prefer that someone else that is familiar with how we run benchmarks takes the time to correctly profile this change. |
Sorry, something went wrong.
|
Using python -m pyperf timeit --rigorous -s "d = {0:0}" 'for _ in d.items(): pass' I measured a 1% performance gain. Using the _PyTuple_FromArraySteal for the dict.items() case (None is immortal so stealing is allowed) the microbenchmark gain is ~3%. If someone is interested in this, please open a new PR with proper benchmarks from the start. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
gh-140009: Optimize dict object by replacing PyTuple_Pack with PyTuple_FromArray
Summary
This PR replaces PyTuple_Pack with PyTuple_FromArray in Objects/dictobject.c for creating small tuples (size 2).
PyTuple_FromArray is more efficient than PyTuple_Pack because it avoids the overhead of variadic arguments (va_args) processing by taking a pointer to a pre-allocated array of PyObject*.
Changes
Performance Impact
This is part of a general effort to optimize small tuple creation across the codebase. Replacing PyTuple_Pack with PyTuple_FromArray for small, fixed-size tuples reduces call overhead.