On Mon, Aug 14, 2017 at 10:26:48PM -0400, Jeremie Courreges-Anglas wrote: > > So I tinkered with the way ksh(1) tracks memory allocation, trying to > make it faster in the general case. One approach used a RB tree, > I wrote since a simple hash table implementation which seems to work > rather well. > > But the actual problem I'd first like to solve is a corner case. I use > HISTSIZE=20000, and when the actual line count in my histfile approaches > 25000 (1.25 * HISTSIZE), ksh(1) has a hard time handling it. The main > reason is that it calls afree() ~5000 times in a loop, with afree() > traversing the APERM freelist, which contains >20000 elements. This is > expensive. > > For history lines, we don't actually need to keep track of allocations > using an area, history lines are private to history.c and no gc/whatever > is needed there. So here's a diff that just uses strdup(3)/free(3). > > Comments? ok?
I was able to reproduce the problem with a HISTSIZE of 100000 which at 125000 entries rendered my system unusable. With the patch I am running fine with a HISTSIZE of 120000 and have come back several times after hitting the 1.25x threshold. Regression tests pass. Rob > Index: history.c > =================================================================== > RCS file: /d/cvs/src/bin/ksh/history.c,v > retrieving revision 1.64 > diff -u -p -p -u -r1.64 history.c > --- history.c 11 Aug 2017 19:37:58 -0000 1.64 > +++ history.c 15 Aug 2017 01:14:58 -0000 > @@ -428,7 +428,7 @@ histbackup(void) > > if (histptr >= history && last_line != hist_source->line) { > hist_source->line--; > - afree(*histptr, APERM); > + free(*histptr); > histptr--; > last_line = hist_source->line; > } > @@ -613,14 +613,15 @@ histsave(int lno, const char *cmd, int d > #endif > } > > - c = str_save(cmd, APERM); > + if ((c = strdup(cmd)) == NULL) > + internal_errorf(1, "unable to allocate memory"); > if ((cp = strrchr(c, '\n')) != NULL) > *cp = '\0'; > > if (histptr < history + histsize - 1) > histptr++; > else { /* remove oldest command */ > - afree(*history, APERM); > + free(*history); > memmove(history, history + 1, > (histsize - 1) * sizeof(*history)); > } > > > > -- > jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE >