[Python-Dev] extremely slow exit for program having huge (45G) dict (python 2.5.2)
Adam Olsen
rhamph at gmail.com
Mon Dec 22 21:22:56 CET 2008
On Mon, Dec 22, 2008 at 11:01 AM, Mike Coleman <tutufan at gmail.com> wrote:
> Thanks for all of the useful suggestions. Here are some preliminary results.
>
> With still gc.disable(), at the end of the program I first did a
> gc.collect(), which took about five minutes. (So, reason enough not
> to gc.enable(), at least without Antoine's patch.)
>
> After that, I did a .clear() on the huge dict. That's where the time
> is being spent. Doing the suggested "poor man's profiling" (repeated
> backtraces via gdb), for 20 or so samples, one is within libc free,
> but all of the rest are in the same place (same source line) within
> PyObjectFree (see below), sometimes within list_dealloc and sometimes
> within tuple_dealloc. So, apparently a lot of time is being spent in
> this loop:
>
>
> /* Case 3: We have to move the arena towards the end
> * of the list, because it has more free pools than
> * the arena to its right.
>
> ...
>
> /* Locate the new insertion point by iterating over
> * the list, using our nextarena pointer.
> */
> while (ao->nextarena != NULL &&
> nf > ao->nextarena->nfreepools) {
> ao->prevarena = ao->nextarena;
> ao->nextarena = ao->nextarena->nextarena;
> }
>
> Investigating further, from one stop, I used gdb to follow the chain
> of pointers in the nextarena and prevarena directions. There were
> 5449 and 112765 links, respectively. maxarenas is 131072.
>
> Sampling nf at different breaks gives values in the range(10,20).
>
> This loop looks like an insertion sort. If it's the case that only a
> "few" iterations are ever needed for any given free, this might be
> okay--if not, it would seem that this must be quadratic.
>
> I attempted to look further by setting a silent break with counter
> within the loop and another break after the loop to inspect the
> counter, but gdb's been buzzing away on that for 40 minutes without
> coming back. That might mean that there are a lot of passes through
> this loop per free (i.e., that gdb is taking a long time to process
> 100,000 silent breaks), or perhaps I've made a mistake, or gdb isn't
> handling this well.
To make sure that's the correct line please recompile python without
optimizations. GCC happily reorders and merges different parts of a
function.
Adding a counter in C and recompiling would be a lot faster than using
a gdb hook.
--
Adam Olsen, aka Rhamphoryncus
More information about the Python-Dev
mailing list