GeezerVison is showing github.com — gh-113141: Tune MI_SEGMENT_SLICE_SHIFT to 14 for using 16 Kib pages by corona10 · Pull Request #160360 · python/cpython
Conversation
corona10
commented
Oct 22, 2026
•
edited by bedevere-app
Bot
Loading
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
vstinner reacted with heart emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Based on an analysis of python -c "import re", with help from a script
written with Claude and run under gdb.
The effect of reducing the page size differs by object size.
| Scope |
AS-IS pages |
AS-IS resident |
AS-IS live |
AS-IS util |
TO-BE pages |
TO-BE resident |
TO-BE live |
TO-BE util |
| All heaps |
149 |
5480 KiB |
4106 KiB |
75 % |
309 |
4964 KiB |
4102 KiB |
83 % |
| MEM |
46 |
1668 KiB |
1146 KiB |
69 % |
77 |
1420 KiB |
1142 KiB |
80 % |
| OBJECT |
45 |
1604 KiB |
1083 KiB |
68 % |
88 |
1344 KiB |
1083 KiB |
81 % |
| GC |
47 |
2108 KiB |
1841 KiB |
87 % |
133 |
2088 KiB |
1841 KiB |
88 % |
| GC_PRE |
11 |
100 KiB |
35 KiB |
35 % |
11 |
112 KiB |
35 KiB |
32 % |
| <=256 B |
68 |
2540 KiB |
2228 KiB |
88 % |
174 |
2556 KiB |
2228 KiB |
87 % |
| 256 B-2 KiB |
47 |
1636 KiB |
1346 KiB |
82 % |
109 |
1608 KiB |
1346 KiB |
84 % |
| 2-64 KiB |
30 |
1088 KiB |
315 KiB |
29 % |
22 |
584 KiB |
311 KiB |
53 % |
| >64 KiB |
4 |
216 KiB |
216 KiB |
100 % |
4 |
216 KiB |
216 KiB |
100 % |
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
@DinoV @nascheme @mpage
According to the benchmark results, this change reduces memory usage by 3% compared to the baseline, with no performance regression. Although there is no comparison with the default build, the results do confirm a reduction in memory usage.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
// Do not use guarded allocations. The free-threaded GC does not support their block layout.
|
|
|
# define MI_GUARDED 0
|
|
|
// Use 16 KiB pages instead of the default 64 KiB in 64-bit platforms.
|
|
|
// TODO: 32-bit platforms may need tuning too.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may need to tune a 32-bit system, but I prefer to pass at this time.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
@nascheme @DinoV
The results from Tools/gcbench from Thomas show that reducing the page size from 64 KiB to 16 KiB increases GC time by 6–8%, since each collection visits four times as many pages. GC-bound pathological cases are 5–8% slower, while steady-state workloads and pyperformance show no change in total runtime.
Peak RSS is generally unchanged on these large-heap tests, although bigcollect/container shows an 11% increase. That case would be worth a separate follow-up if we decide to merge this PR.
This PR aims to reduce the memory overhead relative to the default build from the current 18% to 15%, as measured by pyperformance. I think we should also compare against the default build using the GC benchmarks to make sure both the performance and memory overheads remain within the guardrails outlined in PEP 779. If both criteria are met, I would like to propose merging this PR.
I’ll share the results once I’ve run the GC benchmarks against the default build.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
corona10
commented
Oct 29, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
Even in GC benchmark this tune does not harmful to the current free-threaded build
(I re-oreganize as pyperf style result)
Benchmarks with tag 'pathology': time
| Benchmark |
default |
FT 64K |
FT 16K |
| gen_frag sparse |
583 ms |
1.12 sec: 1.92x slower |
1.22 sec: 2.10x slower |
| gen_frag churn |
5.07 sec |
3.60 sec: 1.41x faster |
3.97 sec: 1.28x faster |
| gen_frag churn acyclic |
4.63 sec |
2.83 sec: 1.64x faster |
2.95 sec: 1.57x faster |
| bigcollect |
104 ms |
97 ms: 1.07x faster |
103 ms: 1.01x faster |
| container |
446 ms |
382 ms: 1.17x faster |
399 ms: 1.12x faster |
| doctree |
6.19 sec |
4.67 sec: 1.33x faster |
4.90 sec: 1.26x faster |
| migrations |
6.62 sec |
5.02 sec: 1.32x faster |
5.21 sec: 1.27x faster |
| deque |
555 ms |
774 ms: 1.40x slower |
751 ms: 1.35x slower |
| bigbuffers 200KB (†) |
51 ms |
103 ms: 2.00x slower |
96 ms: 1.87x slower |
| bigbuffers 4MB (†) |
3.34 sec |
1.23 sec: 2.72x faster |
417 ms: 8.01x faster |
| ext_buffers_malloc (*) |
549,634 ops/s |
337,796 ops/s: 1.63x slower |
338,180 ops/s: 1.63x slower |
| ext_buffers_pymem |
558,001 ops/s |
325,207 ops/s: 1.72x slower |
301,579 ops/s: 1.85x slower |
| hidden_refs |
1,589,119 ops/s |
470,105 ops/s: 3.38x slower |
499,478 ops/s: 3.18x slower |
| c_globals |
291,985 ops/s |
227,908 ops/s: 1.28x slower |
223,261 ops/s: 1.31x slower |
| py_globals |
283,106 ops/s |
241,875 ops/s: 1.17x slower |
235,612 ops/s: 1.20x slower |
| event_widgets runaway (*) |
33,171 ops/s |
45,872 ops/s: 1.38x faster |
41,341 ops/s: 1.25x faster |
| Geometric mean |
(ref) |
1.13x slower |
1.17x slower |
| Geometric mean incl. (†) |
(ref) |
1.09x slower |
1.05x slower |
Benchmarks with tag 'pathology': peak memory
| Benchmark |
default |
FT 64K |
FT 16K |
| gen_frag sparse |
49 MB |
54 MB: 1.10x |
54 MB: 1.11x |
| gen_frag churn |
90 MB |
88 MB: 0.98x |
88 MB: 0.98x |
| gen_frag churn acyclic |
88 MB |
88 MB: 1.00x |
88 MB: 1.00x |
| bigcollect |
260 MB |
275 MB: 1.06x |
305 MB: 1.17x |
| container |
245 MB |
273 MB: 1.11x |
304 MB: 1.24x |
| doctree |
1,165 MB |
1,208 MB: 1.04x |
1,225 MB: 1.05x |
| migrations |
277 MB |
298 MB: 1.08x |
301 MB: 1.09x |
| deque |
246 MB |
105 MB: 0.43x |
91 MB: 0.37x |
| bigbuffers 200KB |
204 MB |
418 MB: 2.05x |
420 MB: 2.06x |
| bigbuffers 4MB |
1,907 MB |
2,017 MB: 1.06x |
2,031 MB: 1.07x |
| ext_buffers_malloc (*) |
188 MB |
392 MB: 2.08x |
508 MB: 2.70x |
| ext_buffers_pymem |
186 MB |
439 MB: 2.36x |
441 MB: 2.37x |
| hidden_refs |
306 MB |
420 MB: 1.37x |
424 MB: 1.39x |
| c_globals |
124 MB |
170 MB: 1.37x |
173 MB: 1.40x |
| py_globals |
124 MB |
171 MB: 1.38x |
169 MB: 1.36x |
| event_widgets runaway (*) |
188 MB |
2,255 MB: 11.97x |
2,234 MB: 11.85x |
| Geometric mean |
(ref) |
1.39x |
1.43x |
Benchmarks with tag 'workloads': time
| Benchmark |
default |
FT 64K |
FT 16K |
| web_service |
52,525 ops/s |
48,112 ops/s: 1.09x slower |
51,578 ops/s: 1.02x slower |
| orm_session mixed |
2,181 ops/s |
1,759 ops/s: 1.24x slower |
1,785 ops/s: 1.22x slower |
| async_server |
8,841 ops/s |
7,130 ops/s: 1.24x slower |
7,434 ops/s: 1.19x slower |
| json_churn |
64,798 ops/s |
57,431 ops/s: 1.13x slower |
57,336 ops/s: 1.13x slower |
| Geometric mean |
(ref) |
1.17x slower |
1.14x slower |
Benchmarks with tag 'workloads': peak memory
| Benchmark |
default |
FT 64K |
FT 16K |
| web_service |
376 MB |
494 MB: 1.31x |
502 MB: 1.34x |
| orm_session mixed |
85 MB |
124 MB: 1.46x |
126 MB: 1.49x |
| async_server |
43 MB |
57 MB: 1.34x |
55 MB: 1.30x |
| json_churn |
83 MB |
98 MB: 1.17x |
98 MB: 1.18x |
| Geometric mean |
(ref) |
1.32x |
1.32x |
Benchmarks with tag 'threads': time
| Benchmark |
default |
FT 64K |
FT 16K |
| web_service 4t |
61,093 ops/s |
148,439 ops/s: 2.43x faster |
150,626 ops/s: 2.47x faster |
| web_service 8t |
64,679 ops/s |
140,723 ops/s: 2.18x faster |
147,049 ops/s: 2.27x faster |
| orm_session mixed 4t |
2,085 ops/s |
4,975 ops/s: 2.39x faster |
5,266 ops/s: 2.53x faster |
| Geometric mean |
(ref) |
2.33x faster |
2.42x faster |
Benchmarks with tag 'threads': peak memory
| Benchmark |
default |
FT 64K |
FT 16K |
| web_service 4t |
399 MB |
486 MB: 1.22x |
492 MB: 1.23x |
| web_service 8t |
419 MB |
492 MB: 1.17x |
498 MB: 1.19x |
| orm_session mixed 4t |
107 MB |
152 MB: 1.42x |
147 MB: 1.37x |
| Geometric mean |
(ref) |
1.27x |
1.26x |
Overall
- Time geometric mean (21 benchmarks, excluding (†)): FT 64K 1.01x faster, FT 16K 1.01x slower
- Time geometric mean incl. (†) (23): FT 64K 1.02x faster, FT 16K 1.06x faster
- (†) bigbuffers: README says the runs are too short to time; shown but excluded from the main geomean. (*) event_widgets runaway, ext_buffers_malloc: large run-to-run variance.
- Memory usage (23 benchmarks): FT 64K 1.36x, FT 16K 1.38x
- Memory usage without (*) benchmarks (21): FT 64K 1.20x, FT 16K 1.21x
- FT 16K vs FT 64K memory: 1.016x (without (*): 1.006x)
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
nascheme
commented
Oct 30, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
This seems to be a classic time-vs-space tradeoff. Generally, I would lean towards sticking with upstream 64k since it doesn't make a large difference. However, since Donghee did extensive testing and it does seem a small win with no major regressions, this seems safe to change. Another point: if we can port some of the GC optimizations from the default build, doing fewer heap traversals by combining passes, this would likely be a bigger win.
|
corona10 reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
corona10 reacted with thumbs up emoji
Another point: if we can port some of the GC optimizations from the default build, doing fewer heap traversals by combining passes, this would likely be a bigger win.
Yeah, we should collect which points we could simply port to the free-threaded build from the default build; I will create an issue about this.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
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.
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.
|