Skip to content

Commit 3c83df2

Browse files
committed
Now that we're no longer linking arenas together, there's no need to
waste the first pool if malloc happens to return a pool-aligned address. This means the number of pools per arena can now vary by 1. Unfortunately, the code counted up from 0 to a presumed constant number of pools. So changed the increasing "watermark" counter to a decreasing "nfreepools" counter instead, and fiddled various stuff accordingly. This also allowed getting rid of two more macros. Also changed the code to align the first address to a pool boundary instead of a page boundary. These are two parallel sets of macro #defines that happen to be identical now, but the page macros are in theory more restrictive (bigger), and there's simply no reason I can see that it wasn't aligning to the less restrictive pool size all along (the code only relies on pool alignment). Hmm. The "page size" macros aren't used for anything *except* defining the pool size macros, and the comments claim the latter isn't necessary. So this has the feel of a layer of indirection that doesn't serve a purpose; should probably get rid of the page macros now.
1 parent 1230068 commit 3c83df2

1 file changed

Lines changed: 21 additions & 25 deletions

File tree

Objects/obmalloc.c

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,7 @@
163163
* some address space wastage, but this is the most portable way to request
164164
* memory from the system across various platforms.
165165
*/
166-
167-
/* ALLOCATED_ARENA_SIZE is passed to malloc; after alignment, we can't
168-
* count on more than ARENA_SIZE bytes being usable for pools.
169-
*/
170-
#define ALLOCATED_ARENA_SIZE (256 << 10) /* 256KB */
171-
#define ARENA_SIZE (ALLOCATED_ARENA_SIZE - SYSTEM_PAGE_SIZE)
166+
#define ARENA_SIZE (256 << 10) /* 256KB */
172167

173168
#ifdef WITH_MEMORY_LIMITS
174169
#define MAX_ARENAS (SMALL_MEMORY_LIMIT / ARENA_SIZE)
@@ -180,7 +175,6 @@
180175
*/
181176
#define POOL_SIZE SYSTEM_PAGE_SIZE /* must be 2^N */
182177
#define POOL_SIZE_MASK SYSTEM_PAGE_SIZE_MASK
183-
#define ARENA_NB_POOLS (ARENA_SIZE / POOL_SIZE)
184178

185179
/*
186180
* -- End of tunable settings section --
@@ -324,13 +318,10 @@ static uptr *arenas = NULL;
324318
static ulong narenas = 0;
325319
static ulong maxarenas = 0;
326320

327-
/* Number of pools already allocated from the current arena. This is
328-
* initialized to the max # of pools to provoke the first allocation request
329-
* into allocating a new arena.
330-
*/
331-
static uint watermark = ARENA_NB_POOLS;
321+
/* Number of pools still available to be allocated in the current arena. */
322+
static uint nfreepools = 0;
332323

333-
/* Free space start address in current arena. */
324+
/* Free space start address in current arena. This is pool-aligned. */
334325
static block *arenabase = NULL;
335326

336327
#if 0
@@ -360,14 +351,20 @@ dumpem(void *ptr)
360351
static block *
361352
new_arena(void)
362353
{
363-
block *bp = (block *)PyMem_MALLOC(ALLOCATED_ARENA_SIZE);
354+
uint excess; /* number of bytes above pool alignment */
355+
block *bp = (block *)PyMem_MALLOC(ARENA_SIZE);
364356
if (bp == NULL)
365357
return NULL;
366358

367-
watermark = 0;
368-
/* Page-round up */
369-
arenabase = bp + (SYSTEM_PAGE_SIZE -
370-
((off_t )bp & SYSTEM_PAGE_SIZE_MASK));
359+
/* arenabase <- first pool-aligned address in the arena
360+
nfreepools <- number of whole pools that fit after alignment */
361+
arenabase = bp;
362+
nfreepools = ARENA_SIZE / POOL_SIZE;
363+
excess = (uint)bp & POOL_SIZE_MASK;
364+
if (excess != 0) {
365+
--nfreepools;
366+
arenabase += POOL_SIZE - excess;
367+
}
371368

372369
/* Make room for a new entry in the arenas vector. */
373370
if (arenas == NULL) {
@@ -437,13 +434,13 @@ new_arena(void)
437434
* to come from.
438435
* Tricky: Letting B be the arena base address in arenas[I], P belongs to the
439436
* arena if and only if
440-
* B <= P < B + ALLOCATED_ARENA_SIZE
437+
* B <= P < B + ARENA_SIZE
441438
* Subtracting B throughout, this is true iff
442-
* 0 <= P-B < ALLOCATED_ARENA_SIZE
439+
* 0 <= P-B < ARENA_SIZE
443440
* By using unsigned arithmetic, the "0 <=" half of the test can be skipped.
444441
*/
445442
#define ADDRESS_IN_RANGE(P, I) \
446-
((I) < narenas && (uptr)(P) - arenas[I] < (uptr)ALLOCATED_ARENA_SIZE)
443+
((I) < narenas && (uptr)(P) - arenas[I] < (uptr)ARENA_SIZE)
447444
/*==========================================================================*/
448445

449446
/* malloc */
@@ -558,11 +555,10 @@ _PyMalloc_Malloc(size_t nbytes)
558555
/*
559556
* Allocate new pool
560557
*/
561-
if (watermark < ARENA_NB_POOLS) {
562-
/* commit malloc(POOL_SIZE) from the current arena */
558+
if (nfreepools) {
563559
commit_pool:
564-
watermark++;
565-
pool = (poolp )arenabase;
560+
--nfreepools;
561+
pool = (poolp)arenabase;
566562
arenabase += POOL_SIZE;
567563
pool->arenaindex = narenas - 1;
568564
pool->szidx = DUMMY_SIZE_IDX;

0 commit comments

Comments
 (0)