Zprof says there is no change: https://youtu.be/6A-AKesvZKM I also attach zprof result in file. BTW, the patch didn't apply to head or to 23f98c3, I had to make changes manually. Best regards, Sebastian Gniazdowski On 11 October 2015 at 08:20, Bart Schaefer wrote: > On Oct 10, 5:06pm, Bart Schaefer wrote: > } > } This suggests a couple of possible fixes, but I've run out of time to > } experiment right now. > > OK, this is the least intrusive change I can think of that might make > a difference. What this attempts to do is maintain a second pointer > into the list of heaps that tells freeheap() where to start working. > It's set on pushheap() and reset on popheap() so it freeheap() should > avoid searching for free space in some arenas that were completely > filled before pushheap() was called. However, it won't improve the > performance if there are a whole lot of heap arenas each with a small > amount of space available at the time of pushheap(). > > To improve THAT situation, I think we'd have to be willing to "leak" > those small pieces of heap until a popheap() happens, and instead > use at least one new arena following most calls to pushheap(). This > might mean that zsh's memory footprint grows, but on modern hardware > that may not be an issue. > > All tests pass with this change in place, let's see what it does with > Sebastian's 89k array elements. > > > diff --git a/Src/mem.c b/Src/mem.c > index b9569ea..01072a3 100644 > --- a/Src/mem.c > +++ b/Src/mem.c > @@ -127,6 +127,12 @@ static Heap heaps; > > static Heap fheap; > > +/* same as fheap, except in the preceding stack context (it will be the > + * first heap from which space in the current context may be recovered > + * when heap space is freed) */ > + > +static Heap fpop; > + > /**/ > #ifdef ZSH_HEAP_DEBUG > /* > @@ -293,8 +299,11 @@ pushheap(void) > h_push++; > #endif > > + fpop = NULL; > for (h = heaps; h; h = h->next) { > DPUTS(!h->used, "BUG: empty heap"); > + if (!fpop && h->used < ARENA_SIZEOF(h)) > + fpop = h; > hs = (Heapstack) zalloc(sizeof(*hs)); > hs->next = h->sp; > h->sp = hs; > @@ -341,9 +350,10 @@ freeheap(void) > * > * However, if the arena to which fheap points is unused, we want to > * free it, so we have no choice but to do the sweep for a new fheap. > + * fpop is the first heap with free space following pushheap(). > */ > if (fheap && !fheap->sp) > - fheap = NULL; /* We used to do this unconditionally */ > + fheap = fpop; > /* > * In other cases, either fheap is already correct, or it has never > * been set and this loop will do it, or it'll be reset from scratch > @@ -417,7 +427,7 @@ popheap(void) > h_pop++; > #endif > > - fheap = NULL; > + fheap = fpop = NULL; > for (h = heaps; h; h = hn) { > hn = h->next; > if ((hs = h->sp)) { > @@ -443,6 +453,8 @@ popheap(void) > #endif > if (!fheap && h->used < ARENA_SIZEOF(h)) > fheap = h; > + if (!fpop && h->sp && h->sp->used < ARENA_SIZEOF(h)) > + fpop = h; > zfree(hs, sizeof(*hs)); > > hl = h;