guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: out-of-control GC


From: Linas Vepstas
Subject: Re: out-of-control GC
Date: Thu, 14 Sep 2017 14:14:09 -0500

Hi Mark,

Thanks... I'm not sure how to reply. So below I write "Yes, but...".  My
alternative was to ignore your email, but that seems rude.

On Tue, Sep 12, 2017 at 9:24 PM, Mark H Weaver <address@hidden> wrote:

> Hi Linas,
>
> Linas Vepstas <address@hidden> writes:
>
>
> A few observations:
>
> * The (format #f ...) allocates a temporary string output port, and that
>   turns out to be quite a lot of allocation, especially in Guile 2.2.
>   Glancing at the relevant code, I would estimate that it's at least 2.5
>   kilobytes spread over at least 10 heap blocks of various sizes.  It
>   also involves registering a finalizer for the port, and adding to a
>   weak set, both of which are relatively expensive for the GC to deal
>   with.  Using 'number->string' there would reduce memory allocation of
>   the loop above by an order of magnitude or more.
>

Yes but ... that code was meant to be an approximation of the "real" code.
In the "real" code, there's maybe dozen-ish scheme calls, so the estimate
of 2.5KB spread over 10 block might be in the right range. In the "real"
code, there is also maybe 30KB of C++ mallocs, per iteration.  Again, those
mallocs should be "invisible" to bdwgc, but they might serve to fragment
RAM badly.

>
>
> * The fact that you're using 'set!' to mutate 'longer' forces a
>   heap-allocated variable object to be allocated for 'longer', whereas
>   otherwise it could be allocated on the stack.  See section 9.3.4
>   (Variables and the VM) in the Guile 2.2 manual for more on this, and
>   how 'set!' often makes things much less efficient.
>

Heh. I was using set! for this demo, only to clear out the long list.
otherwise, you'd get a multi-billion-entry list, which clearly blows out
the stack.

>
> * Since 'longer' is allocated within the loop, a new copy of that
>   (heap-allocated) variable object is created for each iteration.
>

Hmm. That's interesting, Is that really right? The thing was meant to be a
tail recursive loop, designed to run for some arbitarily long time.
Clearly a heap allocation in a loop would be a disaster.

In my "real" code, I don't think I am using set! in this way (but I will
now have to pay closer attention).  Its not clear that this isn't some kind
of guile design flaw -- I can't imagine a technical reason for why a set!
to a local variable would force it to go on the heap.


> Since you're running this loop about 1.2 billion times, and each
> iteration is allocating at least 2.5k bytes, that comes out to around 3
> terabytes of allocation during this loop.  All of that must be reclaimed
> by the garbage collector.
>

Yeah, the 1.2 billion was to get it to run some 12+ hours, so that I could
verify if it slowly degrades over time (it didn't - it was stable after the
first few minutes).  My loop was running 25 million times, and it took some
12 or 20 hours to finish. And it did seem to slowly degrade, but I'm not
quite sure.


> Also, since the port objects have finalizers,


I don't think that any of my code is using ports in my loop, or that
there's anything else in the loop that needs finalization.

I need to create some better instrumentation.  But at 1-3 days per run,
debugging gets tedious very quickly very fast.  One is not motivated to
revisit the problem, once you finally come out the other end.  Until, of
course, next time.

--linas

-- 
*"The problem is not that artificial intelligence will get too smart and
take over the world," computer scientist Pedro Domingos writes, "the
problem is that it's too stupid and already has." *


reply via email to

[Prev in Thread] Current Thread [Next in Thread]