Subject: bug#45200: [PATCH] Force Glibc to free the memory freed

From: DJ Delorie <[email-masked]>
Date: Wed, 03 Feb 2021 15:42:11 -0500

Stefan Monnier <[email-masked]> writes:
> I understand that as well.  But I'm wondering why glibc is willing to
> keep *indefinitely* an unused 200MB of memory, which is more than double
> the mount of memory in use for the rest of the application's life.

To be blunt, 200Mb is peanuts compared to some applications, and it's
*nothing* compared to an enterprise application.  Keeping 200M around to
quickly satisfy memory requests of various sizes (not all cached chunks
are the same size) is IMHO reasonable.

> I mean I understand that you can't predict the future, but I expected
> that "at some point" glibc should decide that those 200MB have been left
> unused for long enough that they deserve to be returned to the OS.

Where will we store that lifetime information?  Yet another word of
memory used, yet another syscall to check the time?  Or completely
reorganize the malloc internals into an LRU system so we can peel off
the old end, at the expense of performance?

I agree that we could do better at detecting long-unused chunks, but
it's expensive (in terms of both development and runtime) to do so, and
typically at the expense of some other desired metric.

I would ask the Emacs devs why they wait until gc to free() memory
instead of keeping track of uses more accurately and free()ing it right
away.  It's a similar type of compromise.

> The doc of `malloc_trim` suggests it's occasionally called by `free` and
> `mallopt` suggests via `M_TRIM_THRESHOLD` that there's a limit to how
> much extra spare memory glibc keeps around, so this suggests that indeed
> memory is trimmed "every once in a while".

Only when the available memory is "at the top of the heap".  Most cached
memory is not; one unfree'd chunk at the top of the heap can keep the
whole heap in memory.  We used to have code that munmap()'d large
"holes" in the cache, but the resulting performance was horrible.

> so my guess is that in Emacs's case those 200MB of extra memory are
> *not* contiguous?  Would that be it?

Right, or just not at the top of the heap.

> Is there a way for Emacs to ask malloc how much memory (or some
> approximation of it) would be recovered by `malloc_trim`?

Not easily.  You can call mallinfo2() before and after a malloc_trim(),
but then you'd have *done* the trim ;-)

> In our normal use, glibc's tuning works fine.  We're just seeing some
> corner case behaviors which seem clearly undesirable, so I think it
> would make sense to try and arrange for glibc to handle them better.

IIRC the original problem was not an unfreed 100M but an unfreed *many
Gb*.  Those are two different problems.