""" Memory comparision of obmalloc arena/pool schemes. SQ is the status quo: we have to use four separate 4 KiB pools, and each burns 48 bytes for a pool header. PR: Tim's PR. There's one pool spanning 4 pages, with 48 bytes for a pool header in the first page, and 16 bytes to store the arena index in each of the other 3 pages. RT: the radix tree. One 16 KiB block that only "wastes" 48 bytes for the pool header. """ PAGES_PER_POOL = 4 ALIGNMENT = 16 # change to 8 for < Python 3.8 PAGE_SIZE = 2 ** 12 POOL_SIZE = PAGE_SIZE * PAGES_PER_POOL POOL_HEADER_SIZE = 48 def from_block(size, blocksize, overhead): return (blocksize - overhead) // size def from_first_page(size, *, pagesize=PAGE_SIZE): return from_block(size, pagesize, POOL_HEADER_SIZE) # using multiple 4K one-page pools - status quo def nobj_4K(size): return from_first_page(size) * PAGES_PER_POOL # using the PR def nobj_PR(size): return from_first_page(size) + from_block(size, PAGE_SIZE, ALIGNMENT) * ( PAGES_PER_POOL - 1 ) # using the radix tree branch def nobj_RT(size): return from_first_page(size, pagesize=POOL_SIZE) print("pages per pool", PAGES_PER_POOL) print(f"pool size {POOL_SIZE:,}") print("alignment", ALIGNMENT) for size in range(ALIGNMENT, 512 + 1, ALIGNMENT): print("size", size) for tag, f in (("SQ", nobj_4K), ("PR", nobj_PR), ("RT", nobj_RT)): nobj = f(size) waste = POOL_SIZE - nobj * size print(f" {tag} {nobj:4} {waste/POOL_SIZE:5.1%}")