From 5a6b74c2019e47f6fe077fa9df8d95a46e4df6e5 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Tue, 9 Jul 2019 23:19:03 -0700 Subject: [PATCH 1/3] Compute allocated blocks in _Py_GetAllocatedBlocks(). 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. --- Objects/obmalloc.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 622da3ad08fcd4..9066fb0cc9b5f0 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1206,12 +1206,29 @@ static size_t ntimes_arena_allocated = 0; /* High water mark (max value ever seen) for narenas_currently_allocated. */ static size_t narenas_highwater = 0; -static Py_ssize_t _Py_AllocatedBlocks = 0; +static Py_ssize_t raw_allocated_blocks; Py_ssize_t _Py_GetAllocatedBlocks(void) { - return _Py_AllocatedBlocks; + Py_ssize_t n = raw_allocated_blocks; + /* add up allocated blocks for used pools */ + for (uint i = 0; i < maxarenas; ++i) { + uintptr_t base = arenas[i].address; + + /* Skip arenas which are not allocated. */ + if (arenas[i].address == (uintptr_t)NULL) + continue; + + /* visit every pool in the arena */ + assert(base <= (uintptr_t) arenas[i].pool_address); + for (uint j = 0; base < (uintptr_t) arenas[i].pool_address; + ++j, base += POOL_SIZE) { + poolp p = (poolp)base; + n += p->ref.count; + } + } + return n; } @@ -1622,13 +1639,12 @@ _PyObject_Malloc(void *ctx, size_t nbytes) { void* ptr; if (pymalloc_alloc(ctx, &ptr, nbytes)) { - _Py_AllocatedBlocks++; return ptr; } ptr = PyMem_RawMalloc(nbytes); if (ptr != NULL) { - _Py_AllocatedBlocks++; + raw_allocated_blocks++; } return ptr; } @@ -1644,13 +1660,12 @@ _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize) if (pymalloc_alloc(ctx, &ptr, nbytes)) { memset(ptr, 0, nbytes); - _Py_AllocatedBlocks++; return ptr; } ptr = PyMem_RawCalloc(nelem, elsize); if (ptr != NULL) { - _Py_AllocatedBlocks++; + raw_allocated_blocks++; } return ptr; } @@ -1899,10 +1914,10 @@ _PyObject_Free(void *ctx, void *p) return; } - _Py_AllocatedBlocks--; if (!pymalloc_free(ctx, p)) { /* pymalloc didn't allocate this address */ PyMem_RawFree(p); + raw_allocated_blocks--; } } From 05d3912bba9da7858b760829d913f061d7c2756d Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Wed, 10 Jul 2019 09:49:18 -0700 Subject: [PATCH 2/3] Need to align arena base address. Remove unused var 'j'. --- Objects/obmalloc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 9066fb0cc9b5f0..bb154c76ab1814 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1214,16 +1214,16 @@ _Py_GetAllocatedBlocks(void) Py_ssize_t n = raw_allocated_blocks; /* add up allocated blocks for used pools */ for (uint i = 0; i < maxarenas; ++i) { - uintptr_t base = arenas[i].address; - /* Skip arenas which are not allocated. */ - if (arenas[i].address == (uintptr_t)NULL) + if (arenas[i].address == NULL) { continue; + } + + uintptr_t base = (uintptr_t)_Py_ALIGN_UP(arenas[i].address, POOL_SIZE); /* visit every pool in the arena */ assert(base <= (uintptr_t) arenas[i].pool_address); - for (uint j = 0; base < (uintptr_t) arenas[i].pool_address; - ++j, base += POOL_SIZE) { + for (; base < (uintptr_t) arenas[i].pool_address; base += POOL_SIZE) { poolp p = (poolp)base; n += p->ref.count; } From 5dc07709bd17d6e8eb8c5eb279f6b6aa2efee647 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Wed, 10 Jul 2019 09:57:08 -0700 Subject: [PATCH 3/3] Add news. --- .../Core and Builtins/2019-07-10-09-56-47.bpo-37537.OkB0wd.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-07-10-09-56-47.bpo-37537.OkB0wd.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-07-10-09-56-47.bpo-37537.OkB0wd.rst b/Misc/NEWS.d/next/Core and Builtins/2019-07-10-09-56-47.bpo-37537.OkB0wd.rst new file mode 100644 index 00000000000000..abf874475d6d9c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-07-10-09-56-47.bpo-37537.OkB0wd.rst @@ -0,0 +1,3 @@ +Compute allocated pymalloc blocks inside _Py_GetAllocatedBlocks(). This +slows down _Py_GetAllocatedBlocks() but gives a small speedup to +_PyObject_Malloc() and _PyObject_Free().