From 12c8880d52336a84c5b1f4524da890b1abceedcf Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Wed, 12 Jun 2019 21:13:02 -0500 Subject: [PATCH 1/4] first tab - and, with luck, the last ;-) --- Objects/obmalloc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index fc7bef6199466d..ab9857a3bf941c 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1758,7 +1758,12 @@ pymalloc_free(void *ctx, void *p) /* All the rest is arena management. We just freed * a pool, and there are 4 cases for arena mgmt: * 1. If all the pools are free, return the arena to - * the system free(). + * the system free(). Except if this is the last + * arena in the list, keep it to avoid trashing: + * keeping one wholly free arena in the list avoids + * pathological cases where a simple loop would + * otherwise provoke needing to allocate and free an + * arena on every iteration. See bpo-37257. * 2. If this is the only free pool in the arena, * add the arena back to the `usable_arenas` list. * 3. If the "next" arena has a smaller count of free @@ -1767,7 +1772,7 @@ pymalloc_free(void *ctx, void *p) * nfreepools. * 4. Else there's nothing more to do. */ - if (nf == ao->ntotalpools) { + if (nf == ao->ntotalpools && ao->nextarena!= NULL) { /* Case 1. First unlink ao from usable_arenas. */ assert(ao->prevarena == NULL || From 5e2e881acb02028908c0b56036d45e1d7a3d85f5 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" Date: Thu, 13 Jun 2019 02:27:13 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core and Builtins/2019-06-13-02-27-12.bpo-37257.IMxDvT.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-06-13-02-27-12.bpo-37257.IMxDvT.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-06-13-02-27-12.bpo-37257.IMxDvT.rst b/Misc/NEWS.d/next/Core and Builtins/2019-06-13-02-27-12.bpo-37257.IMxDvT.rst new file mode 100644 index 00000000000000..ac8d90fd2998b4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-06-13-02-27-12.bpo-37257.IMxDvT.rst @@ -0,0 +1 @@ +Python's small object allocator (``obmalloc.c``) now allows (no more than) one empty arena to remain available for immediate reuse, without returning it to the OS. This prevents thrashing in simple loops where an arena could be created and destroyed anew on each iteration. \ No newline at end of file From 328dfbea9caf8531a7a8c2425d1b5e9c731b12ac Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Wed, 12 Jun 2019 22:12:29 -0500 Subject: [PATCH 3/4] Update Objects/obmalloc.c Co-Authored-By: Inada Naoki --- Objects/obmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index ab9857a3bf941c..c4554543e60556 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1759,7 +1759,7 @@ pymalloc_free(void *ctx, void *p) * a pool, and there are 4 cases for arena mgmt: * 1. If all the pools are free, return the arena to * the system free(). Except if this is the last - * arena in the list, keep it to avoid trashing: + * arena in the list, keep it to avoid thrashing: * keeping one wholly free arena in the list avoids * pathological cases where a simple loop would * otherwise provoke needing to allocate and free an From 7423ae84225cc351d94c9975bb8cdb9445d5d177 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Wed, 12 Jun 2019 22:12:37 -0500 Subject: [PATCH 4/4] Update Objects/obmalloc.c Co-Authored-By: Inada Naoki --- Objects/obmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index c4554543e60556..622da3ad08fcd4 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1772,7 +1772,7 @@ pymalloc_free(void *ctx, void *p) * nfreepools. * 4. Else there's nothing more to do. */ - if (nf == ao->ntotalpools && ao->nextarena!= NULL) { + if (nf == ao->ntotalpools && ao->nextarena != NULL) { /* Case 1. First unlink ao from usable_arenas. */ assert(ao->prevarena == NULL ||