Skip to content

Commit 5d25f2b

Browse files
authored
bpo-37537: Compute allocated blocks in _Py_GetAllocatedBlocks() (#14680)
Keeping an account of allocated blocks slows down _PyObject_Malloc() and _PyObject_Free() by a measureable amount. Have _Py_GetAllocatedBlocks() iterate over the arenas to sum up the allocated blocks for pymalloc.
1 parent f117d87 commit 5d25f2b

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Compute allocated pymalloc blocks inside _Py_GetAllocatedBlocks(). This
2+
slows down _Py_GetAllocatedBlocks() but gives a small speedup to
3+
_PyObject_Malloc() and _PyObject_Free().

Objects/obmalloc.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,12 +1206,29 @@ static size_t ntimes_arena_allocated = 0;
12061206
/* High water mark (max value ever seen) for narenas_currently_allocated. */
12071207
static size_t narenas_highwater = 0;
12081208

1209-
static Py_ssize_t _Py_AllocatedBlocks = 0;
1209+
static Py_ssize_t raw_allocated_blocks;
12101210

12111211
Py_ssize_t
12121212
_Py_GetAllocatedBlocks(void)
12131213
{
1214-
return _Py_AllocatedBlocks;
1214+
Py_ssize_t n = raw_allocated_blocks;
1215+
/* add up allocated blocks for used pools */
1216+
for (uint i = 0; i < maxarenas; ++i) {
1217+
/* Skip arenas which are not allocated. */
1218+
if (arenas[i].address == NULL) {
1219+
continue;
1220+
}
1221+
1222+
uintptr_t base = (uintptr_t)_Py_ALIGN_UP(arenas[i].address, POOL_SIZE);
1223+
1224+
/* visit every pool in the arena */
1225+
assert(base <= (uintptr_t) arenas[i].pool_address);
1226+
for (; base < (uintptr_t) arenas[i].pool_address; base += POOL_SIZE) {
1227+
poolp p = (poolp)base;
1228+
n += p->ref.count;
1229+
}
1230+
}
1231+
return n;
12151232
}
12161233

12171234

@@ -1622,13 +1639,12 @@ _PyObject_Malloc(void *ctx, size_t nbytes)
16221639
{
16231640
void* ptr;
16241641
if (pymalloc_alloc(ctx, &ptr, nbytes)) {
1625-
_Py_AllocatedBlocks++;
16261642
return ptr;
16271643
}
16281644

16291645
ptr = PyMem_RawMalloc(nbytes);
16301646
if (ptr != NULL) {
1631-
_Py_AllocatedBlocks++;
1647+
raw_allocated_blocks++;
16321648
}
16331649
return ptr;
16341650
}
@@ -1644,13 +1660,12 @@ _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize)
16441660

16451661
if (pymalloc_alloc(ctx, &ptr, nbytes)) {
16461662
memset(ptr, 0, nbytes);
1647-
_Py_AllocatedBlocks++;
16481663
return ptr;
16491664
}
16501665

16511666
ptr = PyMem_RawCalloc(nelem, elsize);
16521667
if (ptr != NULL) {
1653-
_Py_AllocatedBlocks++;
1668+
raw_allocated_blocks++;
16541669
}
16551670
return ptr;
16561671
}
@@ -1899,10 +1914,10 @@ _PyObject_Free(void *ctx, void *p)
18991914
return;
19001915
}
19011916

1902-
_Py_AllocatedBlocks--;
19031917
if (!pymalloc_free(ctx, p)) {
19041918
/* pymalloc didn't allocate this address */
19051919
PyMem_RawFree(p);
1920+
raw_allocated_blocks--;
19061921
}
19071922
}
19081923

0 commit comments

Comments
 (0)