From 338e010b45d7bd411e2bbcedcd8ef195be40c2be Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Mon, 1 Apr 2002 19:23:44 +0000 Subject: [PATCH] Restructured my pool-management overview in terms of the three possible pool states. I think it's much clearer now. Added a new long overdue block-management overview comment block. I believe the comments are in good shape now. Added two comments about possible small optimizations (one getting rid of runtime multiplications at the cost of a new pool_header member; the other getting rid of runtime divisions and the pool_header capacity member, at the cost of a static const vector of 32 uints). --- Objects/obmalloc.c | 82 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 303084422f..94e23d7a83 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -268,27 +268,66 @@ all partially used pools holding small blocks with "size class idx" i. So usedpools[0] corresponds to blocks of size 8, usedpools[2] to blocks of size 16, and so on: index 2*i <-> blocks of size (i+1)<capacity = (POOL_SIZE - POOL_OVERHEAD) / size; + + is invariant across all pools of a given size class, it may make more + sense to compute those at compile-time into a const vector indexed by + size class, and lose the pool->capacity member and the runtime divisions). + + +Block Management + +Blocks within pools are again carved out as needed. pool->freeblock points to +the start of a singly-linked list of free blocks within the pool. When a +block is freed, it's inserted at the front of its pool's freeblock list. Note +that the available blocks in a pool are *not* linked all together when a pool +is initialized. Instead only "the first" (lowest address) block is set up, +setting pool->freeblock to NULL. This is consistent with that pymalloc +strives at all levels (arena, pool, and block) never to touch a piece of +memory until it's actually needed. So long as a pool is in the used state, +we're certain there *is* a block available for allocating. If pool->freeblock +is NULL then, that means we simply haven't yet gotten to one of the higher- +address blocks. The address of "the next" available block can be computed +then from pool->ref.count (the number of currently allocated blocks). This +computation can be expensive, because it requires an integer multiply. +However, so long as the pool's size class doesn't change, it's a one-time cost +for that block; the computation could be made cheaper via adding a highwater +pointer to the pool_header, but the tradeoff is murky. + Major obscurity: While the usedpools vector is declared to have poolp entries, it doesn't really. It really contains two pointers per (conceptual) @@ -510,6 +549,7 @@ error: */ #define ADDRESS_IN_RANGE(P, I) \ ((I) < narenas && (uptr)(P) - arenas[I] < (uptr)ARENA_SIZE) + /*==========================================================================*/ /* malloc */ -- 2.50.1