GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Add huge pages support for pymalloc · Issue #144319 · python/cpython Open Labels interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement Descriptionpymalloc allocates small objects from contiguous regions called arenas. On 64-bit platforms each arena is 1 MiB, obtained via Most modern operating systems support "huge pages": memory pages much larger than the default 4 KiB. On x86_64 Linux the standard huge page size is 2 MiB. A single 2 MiB huge page is covered by one TLB entry instead of 512 entries for the equivalent range of 4 KiB pages. This dramatically reduces TLB pressure for workloads that touch large contiguous allocations. On Linux, explicit huge pages are allocated via I'd like to propose adding a The flag is opt-in and off by default. # Allocate (requires root) echo 128 | sudo tee /proc/sys/vm/nr_hugepages # Verify grep HugePages /proc/meminfo # HugePages_Total: 128 # HugePages_Free: 128 # Make persistent across reboots by adding to /etc/sysctl.conf: # vm.nr_hugepages = 128 Each arena consumes one huge page. If the pool runs out, obmalloc falls back to regular 4K pages transparently. I benchmarked on an i9-14900KS, Linux 6.18.3, GCC 15.2.1 on main with Wall-clock results:
dTLB miss reductions:
The perf command used per benchmark: EVENTS="dTLB-loads,dTLB-load-misses,dTLB-stores,dTLB-store-misses,iTLB-load-misses,cache-misses,cache-references,instructions,cycles,page-faults" perf stat -r 10 -e "$EVENTS" ./python bench_obmalloc.py fragmentation bench_obmalloc.pyimport sys, gc def bench_small_object_churn(): objs = [] for _ in range(200_000): objs.append(bytearray(64)) for _ in range(200_000): objs.append(bytearray(64)); objs.pop(0) def bench_bulk_small_alloc(): objs = [bytearray(48) for _ in range(1_000_000)] for o in objs: o[0] = 1 def bench_dict_churn(): for _ in range(500_000): d = {"a": 1, "b": 2, "c": 3, "d": 4}; del d def bench_mixed_sizes(): sizes = [8, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512] objs = [bytearray(sizes[i % 12]) for i in range(500_000)] def bench_fragmentation(): objs = [bytearray(128) for _ in range(500_000)] for i in range(0, len(objs), 2): objs[i] = None for i in range(0, len(objs), 2): objs[i] = bytearray(128) def bench_list_of_tuples(): objs = [(i, i+1, i+2) for i in range(1_000_000)] def bench_class_instances(): class Pt: __slots__ = ('x', 'y', 'z') def __init__(s, x, y, z): s.x = x; s.y = y; s.z = z objs = [Pt(i, i+1, i+2) for i in range(500_000)] def bench_arena_pressure(): layers = [[bytearray(256) for _ in range(200_000)] for _ in range(10)] def bench_random_walk(): import random; random.seed(42) objs = [bytearray(64) for _ in range(1_000_000)] idx = list(range(len(objs))); random.shuffle(idx) for i in idx: objs[i][0] = i & 0xff BENCHMARKS = dict(small_object_churn=bench_small_object_churn, bulk_small_alloc=bench_bulk_small_alloc, dict_churn=bench_dict_churn, mixed_sizes=bench_mixed_sizes, fragmentation=bench_fragmentation, list_of_tuples=bench_list_of_tuples, class_instances=bench_class_instances, arena_pressure=bench_arena_pressure, random_walk=bench_random_walk) if __name__ == "__main__": gc.collect(); gc.disable(); BENCHMARKS[sys.argv[1]](); gc.enable() Full reproduction: ./configure && make -j$(nproc) && cp python python_default ./configure --with-pymalloc-hugepages && make -j$(nproc) && cp python python_hugepages echo 128 | sudo tee /proc/sys/vm/nr_hugepages EVENTS="dTLB-loads,dTLB-load-misses,dTLB-stores,dTLB-store-misses,iTLB-load-misses,cache-misses,cache-references,instructions,cycles,page-faults" for b in bulk_small_alloc mixed_sizes fragmentation list_of_tuples class_instances arena_pressure random_walk; do echo "=== $b ===" perf stat -r 10 -e "$EVENTS" ./python_default bench_obmalloc.py "$b" perf stat -r 10 -e "$EVENTS" ./python_hugepages bench_obmalloc.py "$b" done Linked PRsReacted by Sergey Miryanov, Chris Eibl, Zverev Konstantin, Hash, iforapsy and Andreas Motl Reacted by Jeremiah Isaacson, Yuki, Ken Jin, Zverev Konstantin, Hash, Joseph Bushagour, Maurycy Pawłowski-Wieroński and Cody Maloney Activity
MetadataMetadataAssigneesLabelsinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement ProjectsMilestoneRelationshipsDevelopmentIssue actions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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. |