GNU bug report logs - #45200
Wishlist: There should be a `malloc-trim' function

Previous Next

Package: emacs;

Reported by: Konstantin Kharlamov <hi-angel <at> yandex.ru>

Date: Sat, 12 Dec 2020 18:44:02 UTC

Severity: wishlist

Fixed in version 29.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 45200 in the body.
You can then email your comments to 45200 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sat, 12 Dec 2020 18:44:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Konstantin Kharlamov <hi-angel <at> yandex.ru>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sat, 12 Dec 2020 18:44:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: bug-gnu-emacs <at> gnu.org
Subject: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sat, 12 Dec 2020 21:43:10 +0300
The problem is basically: (garbage-collect) refuses to collect some of the memory. It is more visible if you delay garbage collection, which is what I do for for performance-related reasons. My config has the following snippet:

    ;; only run garbage collection on idle
    (setq gc-cons-threshold most-positive-fixnum)
    (run-with-idle-timer 2 t (lambda () (garbage-collect)))

How much memory gets lost depends on configuration. For me right after start the difference is 40 MB: ≈60 MB is Emacs PSS size without above code, and ≈100 MB it is when garbage-collection is delayed, *after* I run explicitly (garbage-collect). It is less visible without any other configs, nonetheless it's visible.

# Steps to reproduce:

1. Run `mkdir /tmp/.emacs.d`
2. Run emacs as `HOME=/tmp/ emacs`, and measure its PSS
3. Create a file /tmp/.emacs.d/early-init.el with content:

    ;; only run garbage collection on idle
    (setq gc-cons-threshold most-positive-fixnum)
    (run-with-idle-timer 2 t (lambda () (garbage-collect)))

4. Run emacs as `HOME=/tmp/ emacs`, evaluate (garbage-collect), then measure its PSS

## Expected

Size has no statistically-significant difference, because in both cases we garbage-collected memory.

## Actual

Size without calling explicit garbage-collect, from 3 runs, varied around 41.2..41.7 MB.

Size afterwards, also 3 runs, varied around 45.4..45.5 MB.

This is 4 MB lost. While not much, but as I mentioned it grows as much as to 40MB. The Emacs whose emacslient I'm using to write this email has size 218 MB, and now I wouldn't be surprised if much of that is actually a leaked memory.

# Version

Emacs-git 28.0.50, build from commit abd15e088e99





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sat, 12 Dec 2020 20:17:03 GMT) Full text and rfc822 format available.

Message #8 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sat, 12 Dec 2020 22:15:52 +0200
> From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> Date: Sat, 12 Dec 2020 21:43:10 +0300
> 
> # Steps to reproduce:
> 
> 1. Run `mkdir /tmp/.emacs.d`
> 2. Run emacs as `HOME=/tmp/ emacs`, and measure its PSS
> 3. Create a file /tmp/.emacs.d/early-init.el with content:
> 
>     ;; only run garbage collection on idle
>     (setq gc-cons-threshold most-positive-fixnum)
>     (run-with-idle-timer 2 t (lambda () (garbage-collect)))
> 
> 4. Run emacs as `HOME=/tmp/ emacs`, evaluate (garbage-collect), then measure its PSS
> 
> ## Expected
> 
> Size has no statistically-significant difference, because in both cases we garbage-collected memory.
> 
> ## Actual
> 
> Size without calling explicit garbage-collect, from 3 runs, varied around 41.2..41.7 MB.
> 
> Size afterwards, also 3 runs, varied around 45.4..45.5 MB.

Could be simply the effect of different stack size, since Emacs's GC
is conservative, and when there's doubt whether something is a live
object, it won't GC it.

I think more specific and detailed evidence is needed to prove your
case: which objects were not GC'ed and why.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sat, 12 Dec 2020 22:45:01 GMT) Full text and rfc822 format available.

Message #11 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 13 Dec 2020 01:44:13 +0300
On Sat, 2020-12-12 at 22:15 +0200, Eli Zaretskii wrote:
> > From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> > Date: Sat, 12 Dec 2020 21:43:10 +0300
> >
> > # Steps to reproduce:
> >
> > 1. Run `mkdir /tmp/.emacs.d`
> > 2. Run emacs as `HOME=/tmp/ emacs`, and measure its PSS
> > 3. Create a file /tmp/.emacs.d/early-init.el with content:
> >
> >     ;; only run garbage collection on idle
> >     (setq gc-cons-threshold most-positive-fixnum)
> >     (run-with-idle-timer 2 t (lambda () (garbage-collect)))
> >
> > 4. Run emacs as `HOME=/tmp/ emacs`, evaluate (garbage-collect), then measure
> > its PSS
> >
> > ## Expected
> >
> > Size has no statistically-significant difference, because in both cases we
> > garbage-collected memory.
> >
> > ## Actual
> >
> > Size without calling explicit garbage-collect, from 3 runs, varied around
> > 41.2..41.7 MB.
> >
> > Size afterwards, also 3 runs, varied around 45.4..45.5 MB.
>
> Could be simply the effect of different stack size, since Emacs's GC
> is conservative, and when there's doubt whether something is a live
> object, it won't GC it.
>
> I think more specific and detailed evidence is needed to prove your
> case: which objects were not GC'ed and why.

Alright, fair enough. I crafted up another testcase, it may be better. The following code first temporarily disables GC, then it prints "hello" 1000000 times, and finally it calls GC manually.

I call `emacs -Q`, then measure PSS, then evaluate the code below, then again measure PSS.

    (let ((i 1000000))
      (setq gc-cons-threshold most-positive-fixnum)
      (while (> i 0)
        (print "hello")
        (setq i (- i 1)))
      (garbage-collect))

The loop takes 20-30 seconds for me, I think. PSS before is ≈41M, and PSS after is 266.3M. That is ≈200M of memory just vanished.

Regarding, whether it is stack size:

     λ grep VmStk /proc/283047/status
    VmStk:       132 kB

Apparently, it is not stack size.






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sat, 12 Dec 2020 23:00:02 GMT) Full text and rfc822 format available.

Message #14 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sat, 12 Dec 2020 23:59:32 +0100
Konstantin Kharlamov <hi-angel <at> yandex.ru> writes:

> The loop takes 20-30 seconds for me, I think. PSS before is ≈41M, and
> PSS after is 266.3M. That is ≈200M of memory just vanished.

I get similar results.  `M-x memory-report' shows that *Messages* and
*Echo Area* each group to 9MB, and almost all of that is in `gap-size'.

But that's still a long way from 200MB.  Perhaps Emacs is bouncing the
buffer area around a lot and isn't returning the data to the OS?  (Does
Emacs ever return memory used by buffers to the OS?)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 13 Dec 2020 05:55:01 GMT) Full text and rfc822 format available.

Message #17 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 13 Dec 2020 00:53:57 -0500
> From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> Cc: 45200 <at> debbugs.gnu.org
> Date: Sun, 13 Dec 2020 01:44:13 +0300
> 
> Alright, fair enough. I crafted up another testcase, it may be better. The following code first temporarily disables GC, then it prints "hello" 1000000 times, and finally it calls GC manually.
> 
> I call `emacs -Q`, then measure PSS, then evaluate the code below, then again measure PSS.
> 
>     (let ((i 1000000))
>       (setq gc-cons-threshold most-positive-fixnum)
>       (while (> i 0)
>         (print "hello")
>         (setq i (- i 1)))
>       (garbage-collect))
> 
> The loop takes 20-30 seconds for me, I think. PSS before is ≈41M, and PSS after is 266.3M. That is ≈200M of memory just vanished.

That memory hasn't vanished, it is in your libc's malloc arena,
available for future allocations.  When and if it will be given back
to the OS is up to the specifics of the malloc implementation.  E.g.,
when I do the above on MS-Windows, where malloc is more eager to return
memory to the OS, I end up with just 40 MB footprint, and if I then
invoke GC manually, the memory goes down almost to the original value:
14 MB vs 12 MB after startup.

There are many places on the Internet which explain why the memory
footprint of a program doesn't go back to the original value even
though the program frees all the heap memory it allocated.  I suggest
to read some of those explanations.

> Regarding, whether it is stack size:
> 
>      λ grep VmStk /proc/283047/status
>     VmStk:       132 kB
> 
> Apparently, it is not stack size.

This is a misunderstanding.  The space allocated for the stack doesn't
need to grow.  Values are pushed and popped there depending on the
callstack depth, and Emacs regards anything on the stack that looks
like a Lisp value or a pointer to a Lisp value as an indication that
this Lisp value is in use, and shouldn't be GC'd.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 13 Dec 2020 06:09:02 GMT) Full text and rfc822 format available.

Message #20 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 45200 <at> debbugs.gnu.org, hi-angel <at> yandex.ru
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 13 Dec 2020 01:08:39 -0500
> From: Lars Ingebrigtsen <larsi <at> gnus.org>
> Cc: Eli Zaretskii <eliz <at> gnu.org>,  45200 <at> debbugs.gnu.org
> Date: Sat, 12 Dec 2020 23:59:32 +0100
> 
> Konstantin Kharlamov <hi-angel <at> yandex.ru> writes:
> 
> > The loop takes 20-30 seconds for me, I think. PSS before is ≈41M, and
> > PSS after is 266.3M. That is ≈200M of memory just vanished.
> 
> I get similar results.  `M-x memory-report' shows that *Messages* and
> *Echo Area* each group to 9MB, and almost all of that is in `gap-size'.
> 
> But that's still a long way from 200MB.  Perhaps Emacs is bouncing the
> buffer area around a lot and isn't returning the data to the OS?  (Does
> Emacs ever return memory used by buffers to the OS?)

Yes, Emacs returns buffer memory to the OS when a buffer is killed.
Buffer text memory is usually obtained via mmap, and is returned when
no longer needed.  Buffer text memory is also returned to the OS when
buffers have their gap resized.

I think it isn't buffer memory that takes up most of the space here,
it's memory allocated for all the strings consed by this snippet.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 13 Dec 2020 12:08:02 GMT) Full text and rfc822 format available.

Message #23 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 13 Dec 2020 15:07:46 +0300
On Sun, 2020-12-13 at 00:53 -0500, Eli Zaretskii wrote:
> > From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> > Cc: 45200 <at> debbugs.gnu.org
> > Date: Sun, 13 Dec 2020 01:44:13 +0300
> > 
> > Alright, fair enough. I crafted up another testcase, it may be better. The
> > following code first temporarily disables GC, then it prints "hello" 1000000
> > times, and finally it calls GC manually.
> > 
> > I call `emacs -Q`, then measure PSS, then evaluate the code below, then
> > again measure PSS.
> > 
> >     (let ((i 1000000))
> >       (setq gc-cons-threshold most-positive-fixnum)
> >       (while (> i 0)
> >         (print "hello")
> >         (setq i (- i 1)))
> >       (garbage-collect))
> > 
> > The loop takes 20-30 seconds for me, I think. PSS before is ≈41M, and PSS
> > after is 266.3M. That is ≈200M of memory just vanished.
> 
> That memory hasn't vanished, it is in your libc's malloc arena,
> available for future allocations.  When and if it will be given back
> to the OS is up to the specifics of the malloc implementation.  E.g.,
> when I do the above on MS-Windows, where malloc is more eager to return
> memory to the OS, I end up with just 40 MB footprint, and if I then
> invoke GC manually, the memory goes down almost to the original value:
> 14 MB vs 12 MB after startup.

Your explanation seems likely, because such memory is reused by glibc on later
mallocs, and if I repeat the testcase, I can see that memory does not increase
further, meaning it got reused.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 15:25:02 GMT) Full text and rfc822 format available.

Message #26 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
To: 45200 <at> debbugs.gnu.org
Subject: [PATCH] Force Glibc to free the memory freed
Date: Sun, 24 Jan 2021 18:24:02 +0300
configure.ac: check whether malloc_trim is suported
src/alloc.c (lisp_free): call malloc_trim() if possible
(bug#45200)
---
 configure.ac | 3 +++
 src/alloc.c  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/configure.ac b/configure.ac
index bcc0be7de0..3e0459a0e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4544,6 +4544,9 @@ AC_DEFUN
 dnl the current CFLAGS etc.
 AC_CHECK_FUNCS(snprintf)
 
+
+AC_CHECK_FUNCS(malloc_trim)
+
 dnl Check for glib.  This differs from other library checks in that
 dnl Emacs need not link to glib unless some other library is already
 dnl linking to glib.  Although glib provides no facilities that Emacs
diff --git a/src/alloc.c b/src/alloc.c
index c0a55e61b9..97e3ceb52c 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1047,6 +1047,9 @@ lisp_free (void *block)
 
   MALLOC_BLOCK_INPUT;
   free (block);
+#ifdef HAVE_MALLOC_TRIM
+  malloc_trim(0); /* work around for high memory consumption, see bug 45200 */
+#endif /* HAVE_MALLOC_TRIM */
 #ifndef GC_MALLOC_CHECK
   mem_delete (mem_find (block));
 #endif
-- 
2.30.0





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 15:41:02 GMT) Full text and rfc822 format available.

Message #29 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Sun, 24 Jan 2021 17:40:29 +0200
> From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
> Date: Sun, 24 Jan 2021 18:24:02 +0300
> 
> configure.ac: check whether malloc_trim is suported
> src/alloc.c (lisp_free): call malloc_trim() if possible
> (bug#45200)
> ---
>  configure.ac | 3 +++
>  src/alloc.c  | 3 +++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/configure.ac b/configure.ac
> index bcc0be7de0..3e0459a0e2 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -4544,6 +4544,9 @@ AC_DEFUN
>  dnl the current CFLAGS etc.
>  AC_CHECK_FUNCS(snprintf)
>  
> +
> +AC_CHECK_FUNCS(malloc_trim)
> +
>  dnl Check for glib.  This differs from other library checks in that
>  dnl Emacs need not link to glib unless some other library is already
>  dnl linking to glib.  Although glib provides no facilities that Emacs
> diff --git a/src/alloc.c b/src/alloc.c
> index c0a55e61b9..97e3ceb52c 100644
> --- a/src/alloc.c
> +++ b/src/alloc.c
> @@ -1047,6 +1047,9 @@ lisp_free (void *block)
>  
>    MALLOC_BLOCK_INPUT;
>    free (block);
> +#ifdef HAVE_MALLOC_TRIM
> +  malloc_trim(0); /* work around for high memory consumption, see bug 45200 */
> +#endif /* HAVE_MALLOC_TRIM */
>  #ifndef GC_MALLOC_CHECK
>    mem_delete (mem_find (block));
>  #endif

Thanks, but is it really a good idea to call malloc_trim each time we
free some chunk of memory?

Carlos, Florian, DJ: any thoughts or comments on this proposal?  (Let
me know if you need some background about the code involved in this.)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 18:52:01 GMT) Full text and rfc822 format available.

Message #32 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 13:51:41 -0500
> # Steps to reproduce:
>
> 1. Run `mkdir /tmp/.emacs.d`
> 2. Run emacs as `HOME=/tmp/ emacs`, and measure its PSS
> 3. Create a file /tmp/.emacs.d/early-init.el with content:
>
>     ;; only run garbage collection on idle
>     (setq gc-cons-threshold most-positive-fixnum)
>     (run-with-idle-timer 2 t (lambda () (garbage-collect)))
>
> 4. Run emacs as `HOME=/tmp/ emacs`, evaluate (garbage-collect), then measure its PSS
>
> ## Expected
>
> Size has no statistically-significant difference, because in both
> cases we garbage-collected memory.

I disagree with this expectation: it is perfectly normal for the amount
of memory allocated to the Emacs process to be left higher if you delay
the GC.  There are various reasons for that:
- fragmentation, of course.  Not much we can do about it short of using
  a moving collector.
- the desire to keep memory around rather than return it to the OS,
  under the assumption that we'll need it again soon.

And it's not considered as a memory leak as long as that memory has
indeed been needed in the past and that future allocations can still
make use of it.

Eli wrote:
> Thanks, but is it really a good idea to call malloc_trim each time we
> free some chunk of memory?

I think if we want to call `malloc_trim`, the obvious place would be to
do it at the end of `garbage_collect`.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 19:01:02 GMT) Full text and rfc822 format available.

Message #35 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 22:00:31 +0300
On Sun, 2021-01-24 at 13:51 -0500, Stefan Monnier wrote:
> > # Steps to reproduce:
> > 
> > 1. Run `mkdir /tmp/.emacs.d`
> > 2. Run emacs as `HOME=/tmp/ emacs`, and measure its PSS
> > 3. Create a file /tmp/.emacs.d/early-init.el with content:
> > 
> >     ;; only run garbage collection on idle
> >     (setq gc-cons-threshold most-positive-fixnum)
> >     (run-with-idle-timer 2 t (lambda () (garbage-collect)))
> > 
> > 4. Run emacs as `HOME=/tmp/ emacs`, evaluate (garbage-collect), then measure
> > its PSS
> > 
> > ## Expected
> > 
> > Size has no statistically-significant difference, because in both
> > cases we garbage-collected memory.
> 
> I disagree with this expectation: it is perfectly normal for the amount
> of memory allocated to the Emacs process to be left higher if you delay
> the GC.  There are various reasons for that:
> - fragmentation, of course.  Not much we can do about it short of using
>   a moving collector.
> - the desire to keep memory around rather than return it to the OS,
>   under the assumption that we'll need it again soon.
> 
> And it's not considered as a memory leak as long as that memory has
> indeed been needed in the past and that future allocations can still
> make use of it.

I'm fine with Emacs possibly keeping a dozen of megabytes for personal use. The problem though is that the issue easily manifests itself in hundreds of megabytes, as can be seen with the testcase marked as "Message #11" in web-ui.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 19:07:01 GMT) Full text and rfc822 format available.

Message #38 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 22:06:21 +0300
On Sun, 2021-01-24 at 22:00 +0300, Konstantin Kharlamov wrote:
> On Sun, 2021-01-24 at 13:51 -0500, Stefan Monnier wrote:
> > > # Steps to reproduce:
> > > 
> > > 1. Run `mkdir /tmp/.emacs.d`
> > > 2. Run emacs as `HOME=/tmp/ emacs`, and measure its PSS
> > > 3. Create a file /tmp/.emacs.d/early-init.el with content:
> > > 
> > >     ;; only run garbage collection on idle
> > >     (setq gc-cons-threshold most-positive-fixnum)
> > >     (run-with-idle-timer 2 t (lambda () (garbage-collect)))
> > > 
> > > 4. Run emacs as `HOME=/tmp/ emacs`, evaluate (garbage-collect), then
> > > measure
> > > its PSS
> > > 
> > > ## Expected
> > > 
> > > Size has no statistically-significant difference, because in both
> > > cases we garbage-collected memory.
> > 
> > I disagree with this expectation: it is perfectly normal for the amount
> > of memory allocated to the Emacs process to be left higher if you delay
> > the GC.  There are various reasons for that:
> > - fragmentation, of course.  Not much we can do about it short of using
> >   a moving collector.
> > - the desire to keep memory around rather than return it to the OS,
> >   under the assumption that we'll need it again soon.
> > 
> > And it's not considered as a memory leak as long as that memory has
> > indeed been needed in the past and that future allocations can still
> > make use of it.
> 
> I'm fine with Emacs possibly keeping a dozen of megabytes for personal use.
> The problem though is that the issue easily manifests itself in hundreds of
> megabytes, as can be seen with the testcase marked as "Message #11" in web-ui.

Case in point btw: after the previous weekend I found my Emacs instance that I did not touch during the weekend to bloat to as much as 6xxMB. I think that happened because the on-idle hook that I hooked garbage collector onto was not run for 2 days, whilst Emacs might have been doing something like communication to LSP server from time to time, so this is why it ended up taking so much memory. I think it's needless to say that I had to restart Emacs for the half-gigabyte of memory to get returned to my system.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 19:13:01 GMT) Full text and rfc822 format available.

Message #41 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 14:12:20 -0500
> I'm fine with Emacs possibly keeping a dozen of megabytes for personal
> use. The problem though is that the issue easily manifests itself in
> hundreds of megabytes, as can be seen with the testcase marked as "Message
> #11" in web-ui.

I don't think the exact number matters: you were willing to make use of
*any* amount of extra memory by delaying all GC until idle time.
The fact that the GC you finally do after that long wait doesn't recover
that memory is not a failure in my book: there's no reason Emacs or
glibc should presume that you won't be reusing just as much heap space
before the next GC.

IOW in my book, you got what you asked for ;-)

BTW, I wish `malloc_trim` could be passed an argument that says
something like "release about half of the free memory", which would
provide a better balance between "hoard free memory indefinitely" and
"constantly free&reallocate memory from the OS".

Also, the manpage of mallopt suggests that glibc should automatically
do the trim on its own every once in a while anyway, so maybe the
problem won't be solved by `malloc_trim`.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 19:56:01 GMT) Full text and rfc822 format available.

Message #44 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 21:55:00 +0200
> From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> Date: Sun, 24 Jan 2021 22:06:21 +0300
> Cc: 45200 <at> debbugs.gnu.org
> 
> Case in point btw: after the previous weekend I found my Emacs instance that I did not touch during the weekend to bloat to as much as 6xxMB. I think that happened because the on-idle hook that I hooked garbage collector onto was not run for 2 days, whilst Emacs might have been doing something like communication to LSP server from time to time, so this is why it ended up taking so much memory. I think it's needless to say that I had to restart Emacs for the half-gigabyte of memory to get returned to my system.

That bug (bug#43389) was recently tracked down and fixed.  I don't
think it has anything to do with malloc_trim and friends.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 20:02:02 GMT) Full text and rfc822 format available.

Message #47 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 23:00:50 +0300
On Sun, 2021-01-24 at 14:12 -0500, Stefan Monnier wrote:
> > I'm fine with Emacs possibly keeping a dozen of megabytes for personal
> > use. The problem though is that the issue easily manifests itself in
> > hundreds of megabytes, as can be seen with the testcase marked as "Message
> > #11" in web-ui.
> 
> I don't think the exact number matters: you were willing to make use of
> *any* amount of extra memory by delaying all GC until idle time.
> The fact that the GC you finally do after that long wait doesn't recover
> that memory is not a failure in my book: there's no reason Emacs or
> glibc should presume that you won't be reusing just as much heap space
> before the next GC.
> 
> IOW in my book, you got what you asked for ;-)

This doesn't look right. I mean, sure, I might need the heap again. Or I might
not. I don't know. Neither you can. Nobody knows. If glibc can predict the
future then fine. But my experience as part of this report suggests glibc can't.

Glibc could for example use statistics of previous allocation patterns to see if
it's needed to release memory and how much, but this is not what happens. And I
am not the only dissatisfied user. Ruby for example too¹. Also, many people
experience strange memory usage grow with Qutebrowser that nobody knows where
it's coming from; and after today's research I suspect Glibc is the culprit (I
don't have yet enough evidence because my Qutebrowser instance doesn't have much
uptime ATM, but attaching to it with gdb and calling `malloc_trim` inside it
already freed ≈40M of memory to me today). Glib also seems affected².

With so many unhappy users, do you still think nothing wrong with the glibc
allocator? It seems to me, we're doing perfectly valid usecase: we used memory,
we don't need it anymore, we free it. If somebody ever notes that malloc/free
cycle takes too much time for them, then they know they need to optimize the
specific codepath where this happens. It's a nice bonus if Glibc could do
malloc/free faster, but not so much if this causes other problems, especially
given it's a core system library.

> BTW, I wish `malloc_trim` could be passed an argument that says
> something like "release about half of the free memory", which would
> provide a better balance between "hoard free memory indefinitely" and
> "constantly free&reallocate memory from the OS".
> 
> Also, the manpage of mallopt suggests that glibc should automatically
> do the trim on its own every once in a while anyway, so maybe the
> problem won't be solved by `malloc_trim`.

Yeah, I've seen that too. Idk why it doesn't work, but that `malloc_trim()` does
I know because I tested it with the testcase where previously Emacs was never
returning ≈200M of memory.

1:
https://www.joyfulbikeshedding.com/blog/2019-03-14-what-causes-ruby-memory-bloat.html#investigating-fragmentation-at-the-memory-allocator-level
2: https://gitlab.gnome.org/GNOME/glib/-/issues/2057





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 20:12:01 GMT) Full text and rfc822 format available.

Message #50 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 22:11:46 +0200
> From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> Date: Sun, 24 Jan 2021 23:00:50 +0300
> Cc: 45200 <at> debbugs.gnu.org
> 
> With so many unhappy users, do you still think nothing wrong with the glibc
> allocator?

Please be aware that this is not the right place to send bug reports
about glibc's memory allocation algorithms and implementation.  They
have their own bug tracker.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 20:22:02 GMT) Full text and rfc822 format available.

Message #53 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 23:21:09 +0300
On Sun, 2021-01-24 at 22:11 +0200, Eli Zaretskii wrote:
> > From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> > Date: Sun, 24 Jan 2021 23:00:50 +0300
> > Cc: 45200 <at> debbugs.gnu.org
> > 
> > With so many unhappy users, do you still think nothing wrong with the glibc
> > allocator?
> 
> Please be aware that this is not the right place to send bug reports
> about glibc's memory allocation algorithms and implementation.  They
> have their own bug tracker.

Sure, they have my report on the problem. In my text I was just trying to convince Stefan that this is not correct behaviour, whereas he was implying otherwise.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 21:21:02 GMT) Full text and rfc822 format available.

Message #56 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 16:20:22 -0500
> Sure, they have my report on the problem. In my text I was just trying to
> convince Stefan that this is not correct behaviour, whereas he was
> implying otherwise.

I'm not saying it's necessarily correct behavior.
What I'm saying is that the expectation that the temporary use of 200MB
should not affect the memory use later is unrealistic.

And also that if you (setq gc-cons-threshold most-positive-fixnum)
then you're simply asking for trouble unless you *really* know what
you're doing (in which case you'd understand that the above expectation
is unrealistic).

> Glibc could for example use statistics of previous allocation patterns
> to see if it's needed to release memory and how much, but this is not
> what happens. And I am not the only dissatisfied user. Ruby for
> example too¹. Also, many people experience strange memory usage grow
> with Qutebrowser that nobody knows where it's coming from; and after
> today's research I suspect Glibc is the culprit (I don't have yet
> enough evidence because my Qutebrowser instance doesn't have much
> uptime ATM, but attaching to it with gdb and calling `malloc_trim`
> inside it already freed ≈40M of memory to me today). Glib also seems
> affected².

Memory management is hard, and lots and lots of things can go wrong.
Maybe you're right and they're all due to some underlying problem
in glibc.  I suspect that instead the only thing in common is that
they're all problems with the memory management.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 21:27:02 GMT) Full text and rfc822 format available.

Message #59 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Mon, 25 Jan 2021 00:26:45 +0300
On Sun, 2021-01-24 at 16:20 -0500, Stefan Monnier wrote:
> > Sure, they have my report on the problem. In my text I was just trying to
> > convince Stefan that this is not correct behaviour, whereas he was
> > implying otherwise.
> 
> I'm not saying it's necessarily correct behavior.
> What I'm saying is that the expectation that the temporary use of 200MB
> should not affect the memory use later is unrealistic.
> 
> And also that if you (setq gc-cons-threshold most-positive-fixnum)
> then you're simply asking for trouble unless you *really* know what
> you're doing (in which case you'd understand that the above expectation
> is unrealistic).

Why unrealistic? To me the situation is pretty clear: I needed 200M, but I don't
need them anymore, so I want them released. What's unrealistic about that?

If that was your point about that "maybe the 200M of memory will be needed
again", then as I said, yeah, maybe, maybe not — unless Glibc has a prophet
module built-in, it can't know, so it should not behave as if it does.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 21:42:02 GMT) Full text and rfc822 format available.

Message #62 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 24 Jan 2021 16:41:04 -0500
> Why unrealistic? To me the situation is pretty clear: I needed 200M, but I don't
> need them anymore, so I want them released. What's unrealistic about that?

What can I say: it's not realistic and I already gave you two technical
reasons why that is.

> If that was your point about that "maybe the 200M of memory will be
> needed again", then as I said, yeah, maybe, maybe not — unless Glibc
> has a prophet module built-in, it can't know, so it should not behave
> as if it does.

Maybe so.  But to the extent that you consciously decided it's OK for
Emacs to use 200MB at time-step A, then you basically lost the "moral
authority" to say that it's not OK for Emacs to still uses up 200MB at
time-step B.

If you can show a similar excessive use of memory without doing
something like (setq gc-cons-threshold most-positive-fixnum), the
question becomes quite different.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 24 Jan 2021 21:56:02 GMT) Full text and rfc822 format available.

Message #65 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Mon, 25 Jan 2021 00:55:36 +0300
On Sun, 2021-01-24 at 16:41 -0500, Stefan Monnier wrote:
> > Why unrealistic? To me the situation is pretty clear: I needed 200M, but I
> > don't
> > need them anymore, so I want them released. What's unrealistic about that?
> 
> What can I say: it's not realistic and I already gave you two technical
> reasons why that is.

What 2 reasons? The reason I had the paragraph below is that I was sure I
answered to everything you said, so I have no idea what you mean. 

> > If that was your point about that "maybe the 200M of memory will be
> > needed again", then as I said, yeah, maybe, maybe not — unless Glibc
> > has a prophet module built-in, it can't know, so it should not behave
> > as if it does.
> 
> Maybe so.  But to the extent that you consciously decided it's OK for
> Emacs to use 200MB at time-step A, then you basically lost the "moral
> authority" to say that it's not OK for Emacs to still uses up 200MB at
> time-step B.

Okay, so, my point you replied to was that I allocated 200M when I needed them, and I am releasing them because I no longer need them. You are opposing that with I "lost the moral authority to say that it's not OK for Emacs to still uses up 200MB".

"moral"…? Seriously? ☺ Was that some code of conduct I violated by allocating 200M, or what does mean "I lost moral authority"? Is that a technical reason you referred to? ☺





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Mon, 25 Jan 2021 22:18:02 GMT) Full text and rfc822 format available.

Message #68 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, monnier <at> iro.umontreal.ca,
 45200 <at> debbugs.gnu.org, Hi-Angel <at> yandex.ru
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Mon, 25 Jan 2021 17:17:27 -0500
Eli Zaretskii <eliz <at> gnu.org> writes:
> Thanks, but is it really a good idea to call malloc_trim each time we
> free some chunk of memory?

malloc_trim() is very expensive relative to free(), partly because of
what it needs to do, and partly because it flushes the fastbins cache.
If you call it every, say, 1000 iterations of free, that might suffice.
Or perhaps after each GC run.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Mon, 25 Jan 2021 22:29:02 GMT) Full text and rfc822 format available.

Message #71 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 26 Jan 2021 01:28:01 +0300
On Mon, 2021-01-25 at 17:17 -0500, DJ Delorie wrote:
> Eli Zaretskii <eliz <at> gnu.org> writes:
> > Thanks, but is it really a good idea to call malloc_trim each time we
> > free some chunk of memory?
> 
> malloc_trim() is very expensive relative to free(), partly because of
> what it needs to do, and partly because it flushes the fastbins cache.
> If you call it every, say, 1000 iterations of free, that might suffice.
> Or perhaps after each GC run.

(un-ccing Glibc maintainers as this question is Emacs-specific)

After a GC run, would that be at the end of `garbage_collect` function as Stefan
mentioned?





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Tue, 26 Jan 2021 14:50:02 GMT) Full text and rfc822 format available.

Message #74 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: DJ Delorie <dj <at> redhat.com>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, monnier <at> iro.umontreal.ca,
 45200 <at> debbugs.gnu.org, Hi-Angel <at> yandex.ru
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 26 Jan 2021 16:49:53 +0200
> From: DJ Delorie <dj <at> redhat.com>
> Cc: Hi-Angel <at> yandex.ru, 45200 <at> debbugs.gnu.org, monnier <at> iro.umontreal.ca,
>         carlos <at> redhat.com, fweimer <at> redhat.com
> Date: Mon, 25 Jan 2021 17:17:27 -0500
> 
> Eli Zaretskii <eliz <at> gnu.org> writes:
> > Thanks, but is it really a good idea to call malloc_trim each time we
> > free some chunk of memory?
> 
> malloc_trim() is very expensive relative to free(), partly because of
> what it needs to do, and partly because it flushes the fastbins cache.

How expensive?  Can you give some quantitative measure?

> If you call it every, say, 1000 iterations of free, that might suffice.
> Or perhaps after each GC run.

There's no guarantee that a full GC will call 'free', even though
that's quite likely.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Tue, 26 Jan 2021 14:56:01 GMT) Full text and rfc822 format available.

Message #77 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 26 Jan 2021 16:55:55 +0200
> From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> Cc: 45200 <at> debbugs.gnu.org, monnier <at> iro.umontreal.ca
> Date: Tue, 26 Jan 2021 01:28:01 +0300
> 
> On Mon, 2021-01-25 at 17:17 -0500, DJ Delorie wrote:
> > Eli Zaretskii <eliz <at> gnu.org> writes:
> > > Thanks, but is it really a good idea to call malloc_trim each time we
> > > free some chunk of memory?
> > 
> > malloc_trim() is very expensive relative to free(), partly because of
> > what it needs to do, and partly because it flushes the fastbins cache.
> > If you call it every, say, 1000 iterations of free, that might suffice.
> > Or perhaps after each GC run.
> 
> (un-ccing Glibc maintainers as this question is Emacs-specific)

Please don't, I invited them to these discussions because they can
help us make the right decisions.

> After a GC run, would that be at the end of `garbage_collect` function as Stefan
> mentioned?

That'd be easy to implement, but I'm not yet sure it's the best
alternative.  In particular, I'd like to have some idea regarding how
much time such a call could take.  In some usage patterns Emacs calls
GC very frequently, which slows down command execution and makes Emacs
less responsive.  So much so that some people raise the GC threshold
too high trying to avoid this slowdown, and raising the threshold too
much is generally not a good idea.  I don't want us to slow GC down
even more so that more people would shoot themselves in the foot by
raising the threshold.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Tue, 26 Jan 2021 15:07:01 GMT) Full text and rfc822 format available.

Message #80 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 26 Jan 2021 18:02:06 +0300
On Tue, 2021-01-26 at 16:55 +0200, Eli Zaretskii wrote:
> > From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> > Cc: 45200 <at> debbugs.gnu.org, monnier <at> iro.umontreal.ca
> > Date: Tue, 26 Jan 2021 01:28:01 +0300
> > 
> > On Mon, 2021-01-25 at 17:17 -0500, DJ Delorie wrote:
> > > Eli Zaretskii <eliz <at> gnu.org> writes:
> > > > Thanks, but is it really a good idea to call malloc_trim each time we
> > > > free some chunk of memory?
> > > 
> > > malloc_trim() is very expensive relative to free(), partly because of
> > > what it needs to do, and partly because it flushes the fastbins cache.
> > > If you call it every, say, 1000 iterations of free, that might suffice.
> > > Or perhaps after each GC run.
> > 
> > (un-ccing Glibc maintainers as this question is Emacs-specific)
> 
> Please don't, I invited them to these discussions because they can
> help us make the right decisions.

Sorry, okay.

> > After a GC run, would that be at the end of `garbage_collect` function as
> > Stefan
> > mentioned?
> 
> That'd be easy to implement, but I'm not yet sure it's the best
> alternative.  In particular, I'd like to have some idea regarding how
> much time such a call could take.  In some usage patterns Emacs calls
> GC very frequently, which slows down command execution and makes Emacs
> less responsive.  So much so that some people raise the GC threshold
> too high trying to avoid this slowdown, and raising the threshold too
> much is generally not a good idea.  I don't want us to slow GC down
> even more so that more people would shoot themselves in the foot by
> raising the threshold.

Yeah, that's true, there's an existing advice to make GC only run on idle. Which is the reason btw this bugreport eventually came to life ☺





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Tue, 26 Jan 2021 15:31:02 GMT) Full text and rfc822 format available.

Message #83 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org,
 Konstantin Kharlamov <hi-angel <at> yandex.ru>
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 26 Jan 2021 10:30:07 -0500
> That'd be easy to implement, but I'm not yet sure it's the best
> alternative.  In particular, I'd like to have some idea regarding how
> much time such a call could take.  In some usage patterns Emacs calls
> GC very frequently, which slows down command execution and makes Emacs
> less responsive.

The most important case where this happens is during phases of creation
of large new structures (e.g. while loading a large package like Org),
where a lot of memory is allocated without generating much garbage, so
every time we run the GC that time is mostly wasted (since we don't
recover any garbage) and calling malloc_trim would also be useless in
those cases.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Tue, 26 Jan 2021 16:15:02 GMT) Full text and rfc822 format available.

Message #86 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, monnier <at> iro.umontreal.ca,
 45200 <at> debbugs.gnu.org, Hi-Angel <at> yandex.ru
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 26 Jan 2021 11:13:52 -0500
Eli Zaretskii <eliz <at> gnu.org> writes:
>> malloc_trim() is very expensive relative to free(), partly because of
>> what it needs to do, and partly because it flushes the fastbins cache.
>
> How expensive?  Can you give some quantitative measure?

malloc_trim() is to free() as garbage collection is to just dropping a
reference.

>> If you call it every, say, 1000 iterations of free, that might suffice.
>> Or perhaps after each GC run.
>
> There's no guarantee that a full GC will call 'free', even though
> that's quite likely.

malloc_trim() is our garbage collector, if you call it after GC that
would be "appropriate" at least ;-)





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Tue, 02 Feb 2021 21:18:02 GMT) Full text and rfc822 format available.

Message #89 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>, Eli Zaretskii <eliz <at> gnu.org>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 00:17:02 +0300
[Message part 1 (text/plain, inline)]
On Tue, 2021-01-26 at 10:30 -0500, Stefan Monnier wrote:
> > That'd be easy to implement, but I'm not yet sure it's the best
> > alternative.  In particular, I'd like to have some idea regarding how
> > much time such a call could take.  In some usage patterns Emacs calls
> > GC very frequently, which slows down command execution and makes Emacs
> > less responsive.
>
> The most important case where this happens is during phases of creation
> of large new structures (e.g. while loading a large package like Org),
> where a lot of memory is allocated without generating much garbage, so
> every time we run the GC that time is mostly wasted (since we don't
> recover any garbage) and calling malloc_trim would also be useless in
> those cases.

So, I just did some benchmarking; the patch I bencharked it with was modified per Stefan's comment (i.e. `malloc_trim(0)` is moved to the end of `garbage_collec()`). I'm attaching it here as well.

Benchamarking was done as follows: I ran built emacs as `src/emacs -Q`; and used this code

    (benchmark-run
        (let ((i 1000000))
          (while (> i 0)
            (print "hello")
            (setq i (- i 1)))))

which I ran 3 times. First with the patch; then I git-checked out HEAD^ (i.e. to the code without my patch), built it, and ran 3 times again.

This code you may recognize, it was the reproducer to show Emacs taking 200M of memory, except I cut out the line disabling GC, and the line that calls GC manually. IOW I used a known memory-heavy testcase, and ran it with vanilla Emacs configuration.

Results are:

    with malloc_trim:
        (8.920371394 232 2.106283245)
        (9.038083601 231 2.060810826)
        (9.140798641 231 2.0594013240000004)

    without malloc_trim:
        (8.987097209 232 2.070143482)
        (8.700478084 231 1.7745506179999997)
        (8.781121056 231 1.7870093610000004)

The difference is just 3-4% (8.7 / 9 ≈ 0.9666666667). It looks to me insignificant enough to not show up anywhere during interactive work with Emacs.

[1.patch (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 04:46:02 GMT) Full text and rfc822 format available.

Message #92 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, Eli Zaretskii <eliz <at> gnu.org>,
 dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 02 Feb 2021 23:45:17 -0500
> Results are:
>
>     with malloc_trim:
>         (8.920371394 232 2.106283245)
>         (9.038083601 231 2.060810826)
>         (9.140798641 231 2.0594013240000004)
>
>     without malloc_trim:
>         (8.987097209 232 2.070143482)
>         (8.700478084 231 1.7745506179999997)
>         (8.781121056 231 1.7870093610000004)
>
> The difference is just 3-4% (8.7 / 9 ≈ 0.9666666667). It looks to me
> insignificant enough to not show up anywhere during interactive work
> with Emacs.

It's indeed not too costly, but what about the upside?


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 04:51:02 GMT) Full text and rfc822 format available.

Message #95 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, Eli Zaretskii <eliz <at> gnu.org>,
 dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 02 Feb 2021 23:50:41 -0500
>>     with malloc_trim:
>>         (8.920371394 232 2.106283245)
>>         (9.038083601 231 2.060810826)
>>         (9.140798641 231 2.0594013240000004)
>>
>>     without malloc_trim:
>>         (8.987097209 232 2.070143482)
>>         (8.700478084 231 1.7745506179999997)
>>         (8.781121056 231 1.7870093610000004)
>>
>> The difference is just 3-4% (8.7 / 9 ≈ 0.9666666667). It looks to me
>> insignificant enough to not show up anywhere during interactive work
>> with Emacs.
>
> It's indeed not too costly, but what about the upside?

BTW, maybe a better way forward than trying to convince us that it's
a good default (which could be hard if the upside is a reduction of the
memory use by a few percent: for many people it might be less
relevant/noticeable than the corresponding few percents lost in speed)
is to provide a patch that adds a new *ELisp* function that calls
`malloc_trim`, which you can then add to `post-gc-hook` in your init
file when your usage pattern makes it useful.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 06:05:01 GMT) Full text and rfc822 format available.

Message #98 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, Eli Zaretskii <eliz <at> gnu.org>,
 dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 09:04:21 +0300
On Tue, 2021-02-02 at 23:50 -0500, Stefan Monnier wrote:
> > >     with malloc_trim:
> > >         (8.920371394 232 2.106283245)
> > >         (9.038083601 231 2.060810826)
> > >         (9.140798641 231 2.0594013240000004)
> > > 
> > >     without malloc_trim:
> > >         (8.987097209 232 2.070143482)
> > >         (8.700478084 231 1.7745506179999997)
> > >         (8.781121056 231 1.7870093610000004)
> > > 
> > > The difference is just 3-4% (8.7 / 9 ≈ 0.9666666667). It looks to me
> > > insignificant enough to not show up anywhere during interactive work
> > > with Emacs.
> > 
> > It's indeed not too costly, but what about the upside?
> 
> BTW, maybe a better way forward than trying to convince us that it's
> a good default (which could be hard if the upside is a reduction of the
> memory use by a few percent: for many people it might be less
> relevant/noticeable than the corresponding few percents lost in speed)
> is to provide a patch that adds a new *ELisp* function that calls
> `malloc_trim`, which you can then add to `post-gc-hook` in your init
> file when your usage pattern makes it useful.

Upside indeed is the memory reduction.

Well, I didn't send the patches for my only benefit, but for benefit of others people. The new ELisp function is something that not too many people would benefit from, and I mean, including those who disable GC. That is because it would be an opt-in feature, which you need to know about to enable it, and not many will ever find out about it.

For my-only benefit I could just continue building Emacs with my patch applied locally, as I do now.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 07:08:02 GMT) Full text and rfc822 format available.

Message #101 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 09:07:35 +0200
On February 3, 2021 8:04:21 AM GMT+02:00, Konstantin Kharlamov <hi-angel <at> yandex.ru> wrote:
> On Tue, 2021-02-02 at 23:50 -0500, Stefan Monnier wrote:
> > > >     with malloc_trim:
> > > >         (8.920371394 232 2.106283245)
> > > >         (9.038083601 231 2.060810826)
> > > >         (9.140798641 231 2.0594013240000004)
> > > > 
> > > >     without malloc_trim:
> > > >         (8.987097209 232 2.070143482)
> > > >         (8.700478084 231 1.7745506179999997)
> > > >         (8.781121056 231 1.7870093610000004)
> > > > 
> > > > The difference is just 3-4% (8.7 / 9 ≈ 0.9666666667). It looks
> to me
> > > > insignificant enough to not show up anywhere during interactive
> work
> > > > with Emacs.
> > > 
> > > It's indeed not too costly, but what about the upside?
> > 
> > BTW, maybe a better way forward than trying to convince us that it's
> > a good default (which could be hard if the upside is a reduction of
> the
> > memory use by a few percent: for many people it might be less
> > relevant/noticeable than the corresponding few percents lost in
> speed)
> > is to provide a patch that adds a new *ELisp* function that calls
> > `malloc_trim`, which you can then add to `post-gc-hook` in your init
> > file when your usage pattern makes it useful.
> 
> Upside indeed is the memory reduction.

How much memory reduction?  Can you show the numbers?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 07:16:01 GMT) Full text and rfc822 format available.

Message #104 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>, Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 10:15:19 +0300
On Wed, 2021-02-03 at 09:07 +0200, Eli Zaretskii wrote:
> On February 3, 2021 8:04:21 AM GMT+02:00, Konstantin Kharlamov
> <hi-angel <at> yandex.ru> wrote:
> > On Tue, 2021-02-02 at 23:50 -0500, Stefan Monnier wrote:
> > > > >     with malloc_trim:
> > > > >         (8.920371394 232 2.106283245)
> > > > >         (9.038083601 231 2.060810826)
> > > > >         (9.140798641 231 2.0594013240000004)
> > > > > 
> > > > >     without malloc_trim:
> > > > >         (8.987097209 232 2.070143482)
> > > > >         (8.700478084 231 1.7745506179999997)
> > > > >         (8.781121056 231 1.7870093610000004)
> > > > > 
> > > > > The difference is just 3-4% (8.7 / 9 ≈ 0.9666666667). It looks
> > to me
> > > > > insignificant enough to not show up anywhere during interactive
> > work
> > > > > with Emacs.
> > > > 
> > > > It's indeed not too costly, but what about the upside?
> > > 
> > > BTW, maybe a better way forward than trying to convince us that it's
> > > a good default (which could be hard if the upside is a reduction of
> > the
> > > memory use by a few percent: for many people it might be less
> > > relevant/noticeable than the corresponding few percents lost in
> > speed)
> > > is to provide a patch that adds a new *ELisp* function that calls
> > > `malloc_trim`, which you can then add to `post-gc-hook` in your init
> > > file when your usage pattern makes it useful.
> > 
> > Upside indeed is the memory reduction.
> 
> How much memory reduction?  Can you show the numbers?

Sure. When I run the testcase for the problem that I posted in 3rd email on this thread¹, vanilla Emacs takes up 260.3M of PSS and never goes below, not even upon re-running (garbage-collect) manually. The patched Emacs on the other hand has 64.3M of PSS right after the testcase finishes.

1: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45200#11





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 07:41:02 GMT) Full text and rfc822 format available.

Message #107 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 3 Feb 2021 08:39:48 +0100
> Well, I didn't send the patches for my only benefit, but for benefit
> of others people. The new ELisp function is something that not too
> many people would benefit from, and I mean, including those who
> disable GC.

Does anyone really disable GC and get away with it?

> That is because it would be an opt-in feature, which you
> need to know about to enable it, and not many will ever find out about
> it.

I wouldn't be afraid of that.  In the past months we had a sufficient
number of candidates caring about the memory consumption of their Emacs
sessions.  An opt-out feature OTOH would get us soon a couple of people
who decide that your feature is responsible for some new slowness and
recommend to throw it out.  So making this an opt-in feature and at the
same time giving some recommendations of what users can do when they
detect that their sessions consumes more memory than expected would be a
finely balanced solution IMO.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 08:25:02 GMT) Full text and rfc822 format available.

Message #110 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: martin rudalics <rudalics <at> gmx.at>, Stefan Monnier
 <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 11:23:43 +0300
On Wed, 2021-02-03 at 08:39 +0100, martin rudalics wrote:
>  > Well, I didn't send the patches for my only benefit, but for benefit
>  > of others people. The new ELisp function is something that not too
>  > many people would benefit from, and I mean, including those who
>  > disable GC.
>
> Does anyone really disable GC and get away with it?

Sure. There's for example this post¹, which is probably where I got the idea to only run GC on idle from. The question is highly upvoted, it has 4k views, and the only positive answer basically says "it's okay as long as you got memory" (well, I got memory), and notes that there's also a point in only disabling GC during startup. Similar advice to only disable it during startup has this pretty upvoted reddit post²

Here's another example³, except in this case the author only disables GC while they're inside minibuffer, and enables it back upon exiting. This then got propogated here as well⁴

On top of that, there are countless advices on just increasing the `gc-cons-threshold` (not inifitely increasing, just making some sane larger value), that would surely reinforce an idea of just making GC run only on idle, if one ever comes across such advice or just figures it out.

>  > That is because it would be an opt-in feature, which you
>  > need to know about to enable it, and not many will ever find out about
>  > it.
>
> I wouldn't be afraid of that.  In the past months we had a sufficient
> number of candidates caring about the memory consumption of their Emacs
> sessions.  An opt-out feature OTOH would get us soon a couple of people
> who decide that your feature is responsible for some new slowness and
> recommend to throw it out.  So making this an opt-in feature and at the
> same time giving some recommendations of what users can do when they
> detect that their sessions consumes more memory than expected would be a
> finely balanced solution IMO.

Well, I have 2 things to say on that.

First of, so far the impact seemed to be small. If one ever comes to blame the new feature, they surely should have actual measurements to support that hypothesis.

Second, most importantly, what `malloc_trim(0)` does is it restores the correct behavior. I mean, what's the point of ever freeing memory if it's not freed, right? The problem we're dealing here with is an actual bug in glibc⁵. What this implies is that if the fix indeed hurts performance someplace, well, then it's that this place requires additional performance-related fixes. As opposed to just ignoring the bug because of performance got somewhere decreased. Things like, changing the slow algorithm, or modifying GC behavior for specific usecases…

It is the general rule that correct behavior rarely correlates with good performance. You might for example omit locks in thread-heavy application, and you get better performance at cost of thread races. Things like that.

---------

1: https://emacs.stackexchange.com/questions/34342/is-there-any-downside-to-setting-gc-cons-threshold-very-high-and-collecting-ga
2: https://www.reddit.com/r/emacs/comments/4j828f/til_setq_gcconsthreshold_100000000/d34gbsp/?context=3
3: https://bling.github.io/blog/2016/01/18/why-are-you-changing-gc-cons-threshold/
4: https://javaguirre.me/2016/10/19/fixing-my-performance-problems-on-emacs
5: https://sourceware.org/bugzilla/show_bug.cgi?id=27103






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 09:37:01 GMT) Full text and rfc822 format available.

Message #113 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 3 Feb 2021 10:35:48 +0100
>> Does anyone really disable GC and get away with it?
>
> Sure. There's for example this post¹, which is probably where I got the idea to only run GC on idle from. The question is highly upvoted, it has 4k views, and the only positive answer basically says "it's okay as long as you got memory" (well, I got memory), and notes that there's also a point in only disabling GC during startup. Similar advice to only disable it during startup has this pretty upvoted reddit post²
>
> Here's another example³, except in this case the author only disables GC while they're inside minibuffer, and enables it back upon exiting. This then got propogated here as well⁴
>
> On top of that, there are countless advices on just increasing the `gc-cons-threshold` (not inifitely increasing, just making some sane larger value), that would surely reinforce an idea of just making GC run only on idle, if one ever comes across such advice or just figures it out.

What I meant was if people really disabled GC for the rest of their
session and got away with it.  But that was only a rhetorical question
to which the answer is clearly no.  All the examples you cite have a
culprit - an application that produces too much garbage.  Identifying
those applications would be much better than working around them by
disabling GC, for example, while a user is in a minibuffer dialog.  That
latter case even must have an easy to identify responsible, just that
nobody cares.  And remember that every cons eventually collected must
have been allocated first.  We always pay twice here.

> First of, so far the impact seemed to be small. If one ever comes to
> blame the new feature, they surely should have actual measurements to
> support that hypothesis.

Hardly.  Sometimes we're lucky as in the "The Emacs master is much
slower than the emacs-27 branch" thread.  More often we're not.

> Second, most importantly, what `malloc_trim(0)` does is it restores
> the correct behavior. I mean, what's the point of ever freeing memory
> if it's not freed, right? The problem we're dealing here with is an
> actual bug in glibc⁵. What this implies is that if the fix indeed
> hurts performance someplace, well, then it's that this place requires
> additional performance-related fixes. As opposed to just ignoring the
> bug because of performance got somewhere decreased. Things like,
> changing the slow algorithm, or modifying GC behavior for specific
> usecases…

The important use case IMO is:

- A user detects, maybe after many hours of use, that memory consumption
  increases.

- The user switches on your option and if memory consumption now
  decreases, there's at least a first workaround.

Personally, I never care about Emacs consuming RAM.  On my machine,
Firefox dwarfs everything else in this regard.

martin





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 09:50:02 GMT) Full text and rfc822 format available.

Message #116 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: martin rudalics <rudalics <at> gmx.at>, Stefan Monnier
 <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 12:49:47 +0300
On Wed, 2021-02-03 at 10:35 +0100, martin rudalics wrote:
>  >> Does anyone really disable GC and get away with it?
>  >
>  > Sure. There's for example this post¹, which is probably where I got the
> idea to only run GC on idle from. The question is highly upvoted, it has 4k
> views, and the only positive answer basically says "it's okay as long as you
> got memory" (well, I got memory), and notes that there's also a point in only
> disabling GC during startup. Similar advice to only disable it during startup
> has this pretty upvoted reddit post²
>  >
>  > Here's another example³, except in this case the author only disables GC
> while they're inside minibuffer, and enables it back upon exiting. This then
> got propogated here as well⁴
>  >
>  > On top of that, there are countless advices on just increasing the `gc-
> cons-threshold` (not inifitely increasing, just making some sane larger
> value), that would surely reinforce an idea of just making GC run only on
> idle, if one ever comes across such advice or just figures it out.
> 
> What I meant was if people really disabled GC for the rest of their
> session and got away with it.  But that was only a rhetorical question
> to which the answer is clearly no. 

I'm not sure where you got this answer from. The first link I referred to has a
user which does exactly that, and it is a highly upvoted question with 4k views.

To me that seem to imply the answer is "yes".

>  All the examples you cite have a
> culprit - an application that produces too much garbage.  Identifying
> those applications would be much better than working around them by
> disabling GC, for example, while a user is in a minibuffer dialog.  That
> latter case even must have an easy to identify responsible, just that
> nobody cares. 

Sure, I completely agree with you. But that is orthogonal to the problem of
free()ed memory not actually being freed.

>  And remember that every cons eventually collected must
> have been allocated first.  We always pay twice here.

First of, glibc has per-thread cache (since 2.26 version, I think), specifically for the usecase of apps allcating and freeing memory too often. The cache is not affected by `malloc_trim()`, I was assured by people on #glibc IRC channel on that.

Second, if Emacs indeed sees it's gonna allocate memory again right away, then it shouldn't have even freed the memory in the first place. No free — no malloc_trim().





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 10:36:01 GMT) Full text and rfc822 format available.

Message #119 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: martin rudalics <rudalics <at> gmx.at>, Stefan Monnier
 <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 13:35:35 +0300
On Wed, 2021-02-03 at 12:49 +0300, Konstantin Kharlamov wrote:
> On Wed, 2021-02-03 at 10:35 +0100, martin rudalics wrote:
> >  All the examples you cite have a
> > culprit - an application that produces too much garbage.  Identifying
> > those applications would be much better than working around them by
> > disabling GC, for example, while a user is in a minibuffer dialog.  That
> > latter case even must have an easy to identify responsible, just that
> > nobody cares. 
> 
> Sure, I completely agree with you. But that is orthogonal to the problem of
> free()ed memory not actually being freed.

Sorry, I figured, I might need to elaborate here. The usecase of GC being temporarily disabled is merely a reproducer for the problem with free(). There may be other usecases as well, which is why I consider the questions of "disabling GC" and the "free not freeing memory" kinda separate.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 11:07:02 GMT) Full text and rfc822 format available.

Message #122 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 3 Feb 2021 12:06:14 +0100
>> What I meant was if people really disabled GC for the rest of their
>> session and got away with it.  But that was only a rhetorical question
>> to which the answer is clearly no.
>
> I'm not sure where you got this answer from. The first link I referred to has a
> user which does exactly that, and it is a highly upvoted question with 4k views.

If the first link refers to

1: https://emacs.stackexchange.com/questions/34342/is-there-any-downside-to-setting-gc-cons-threshold-very-high-and-collecting-ga

then

(setq gc-cons-threshold (eval-when-compile (* 1024 1024 1024)))
(run-with-idle-timer 2 t (lambda () (garbage-collect)))

obviously means that this author does GC as soon as Emacs is idle.

> To me that seem to imply the answer is "yes".

Not to me.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 11:09:01 GMT) Full text and rfc822 format available.

Message #125 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: martin rudalics <rudalics <at> gmx.at>, Stefan Monnier
 <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 14:08:06 +0300
On Wed, 2021-02-03 at 12:06 +0100, martin rudalics wrote:
>  >> What I meant was if people really disabled GC for the rest of their
>  >> session and got away with it.  But that was only a rhetorical question
>  >> to which the answer is clearly no.
>  >
>  > I'm not sure where you got this answer from. The first link I referred to
> has a
>  > user which does exactly that, and it is a highly upvoted question with 4k
> views.
> 
> If the first link refers to
> 
> 1:
> https://emacs.stackexchange.com/questions/34342/is-there-any-downside-to-setting-gc-cons-threshold-very-high-and-collecting-ga
> 
> then
> 
> (setq gc-cons-threshold (eval-when-compile (* 1024 1024 1024)))
> (run-with-idle-timer 2 t (lambda () (garbage-collect)))
> 
> obviously means that this author does GC as soon as Emacs is idle.

Yes. I think you misread this thread, the case where the problem first came up is exactly running GC on idle.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 11:18:02 GMT) Full text and rfc822 format available.

Message #128 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: martin rudalics <rudalics <at> gmx.at>, Stefan Monnier
 <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 14:16:53 +0300
On Wed, 2021-02-03 at 14:08 +0300, Konstantin Kharlamov wrote:
> On Wed, 2021-02-03 at 12:06 +0100, martin rudalics wrote:
> >  >> What I meant was if people really disabled GC for the rest of their
> >  >> session and got away with it.  But that was only a rhetorical question
> >  >> to which the answer is clearly no.
> >  >
> >  > I'm not sure where you got this answer from. The first link I referred to
> > has a
> >  > user which does exactly that, and it is a highly upvoted question with 4k
> > views.
> > 
> > If the first link refers to
> > 
> > 1:
> > https://emacs.stackexchange.com/questions/34342/is-there-any-downside-to-setting-gc-cons-threshold-very-high-and-collecting-ga
> > 
> > then
> > 
> > (setq gc-cons-threshold (eval-when-compile (* 1024 1024 1024)))
> > (run-with-idle-timer 2 t (lambda () (garbage-collect)))
> > 
> > obviously means that this author does GC as soon as Emacs is idle.
> 
> Yes. I think you misread this thread, the case where the problem first came up
> is exactly running GC on idle.

But either way, I'm not sure why it matters. If you want, I can for you specifically craft up a reproducer that works with GC running on idle. The reason I haven't done this in the first place is just to simplify the reproducer, but if it's something you're interested in, just ping me up, I'll make one.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 12:57:02 GMT) Full text and rfc822 format available.

Message #131 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 3 Feb 2021 13:56:04 +0100
> Yes. I think you misread this thread, the case where the problem first
> came up is exactly running GC on idle.

In your "Force Glibc to free the memory freed" patch I nowhere see that
you do that only when running GC on idle.  What am I missing?

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 13:01:02 GMT) Full text and rfc822 format available.

Message #134 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: martin rudalics <rudalics <at> gmx.at>, Stefan Monnier
 <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 16:00:42 +0300
On Wed, 2021-02-03 at 13:56 +0100, martin rudalics wrote:
>  > Yes. I think you misread this thread, the case where the problem first
>  > came up is exactly running GC on idle.
> 
> In your "Force Glibc to free the memory freed" patch I nowhere see that
> you do that only when running GC on idle.  What am I missing?

Haha, you seem to have jumped over explanations straight to discussing a discussion about an alternative implementation, even though the discussion has never happened :D

Now I see what you mean, your idea is to run `malloc_trim(0)` only on idle. That sounds okay with me.

Stefan, what do you think? Will it be okay if I implement a patch that runs `malloc_trim(0)` when Emacs is idle?





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 14:45:02 GMT) Full text and rfc822 format available.

Message #137 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 16:44:17 +0200
> From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> Date: Wed, 03 Feb 2021 11:23:43 +0300
> Cc: carlos <at> redhat.com, fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org, dj <at> redhat.com
> 
> Second, most importantly, what `malloc_trim(0)` does is it restores the correct behavior. I mean, what's the point of ever freeing memory if it's not freed, right?

The purpose of freeing memory is to make it available for further
allocations by the program.  You seem to interpret "freeing memory" to
mean that memory should be returned to the OS, but that's not
necessarily true, and isn't required to allow the freeing program be
able to allocate more memory in the future.

> The problem we're dealing here with is an actual bug in glibc⁵. What this implies is that if the fix indeed hurts performance someplace, well, then it's that this place requires additional performance-related fixes. As opposed to just ignoring the bug because of performance got somewhere decreased. Things like, changing the slow algorithm, or modifying GC behavior for specific usecases…

The fact that the bug you reported didn't get any responses in  more
than a month, let alone wasn't fixed, could be a sign that not
everyone agrees this is a bug...




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 14:52:01 GMT) Full text and rfc822 format available.

Message #140 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 16:51:14 +0200
> From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> Date: Wed, 03 Feb 2021 12:49:47 +0300
> Cc: carlos <at> redhat.com, fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org, dj <at> redhat.com
> 
> Second, if Emacs indeed sees it's gonna allocate memory again right away, then it shouldn't have even freed the memory in the first place.

You are not serious here, are you?  How could Emacs possibly know, at
the level that does GC, whether the Lisp program that currently runs
will need more memory in the future?  The program itself may know that
(and then it may not, if memory is allocated by some low-level
primitive), but GC itself?  If you think it can have powers for such
prophecy, we should probably use that to write a program to advise us
which shares to buy, and get rich -- fast.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 15:02:01 GMT) Full text and rfc822 format available.

Message #143 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 18:01:30 +0300
On Wed, 2021-02-03 at 16:51 +0200, Eli Zaretskii wrote:
> > From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
> > Date: Wed, 03 Feb 2021 12:49:47 +0300
> > Cc: carlos <at> redhat.com, fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org,
> > dj <at> redhat.com
> > 
> > Second, if Emacs indeed sees it's gonna allocate memory again right away,
> > then it shouldn't have even freed the memory in the first place.
> 
> You are not serious here, are you?  How could Emacs possibly know, at
> the level that does GC, whether the Lisp program that currently runs
> will need more memory in the future?  The program itself may know that
> (and then it may not, if memory is allocated by some low-level
> primitive), but GC itself?  If you think it can have powers for such
> prophecy, we should probably use that to write a program to advise us
> which shares to buy, and get rich -- fast.

Yeah, you're right, never mind this text, I think I kinda misinterpreted two sentences I was answering to.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 15:13:02 GMT) Full text and rfc822 format available.

Message #146 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Andreas Schwab <schwab <at> linux-m68k.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com,
 monnier <at> iro.umontreal.ca, Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 16:12:23 +0100
On Feb 03 2021, Eli Zaretskii wrote:

> The purpose of freeing memory is to make it available for further
> allocations by the program.  You seem to interpret "freeing memory" to
> mean that memory should be returned to the OS, but that's not
> necessarily true, and isn't required to allow the freeing program be
> able to allocate more memory in the future.

Especially as asking the OS to (de)allocate memory is a more expensive
operation.

Andreas.

-- 
Andreas Schwab, schwab <at> linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 15:16:02 GMT) Full text and rfc822 format available.

Message #149 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 3 Feb 2021 16:14:54 +0100
> Now I see what you mean, your idea is to run `malloc_trim(0)` only on
> idle. That sounds okay with me.

What I meant was a function say 'garbage-collect-and-trim' that would do
the same as ‘garbage-collect’ but in addition run 'malloc_trim(0)' so
the person that earlier used

(setq gc-cons-threshold (eval-when-compile (* 1024 1024 1024)))
(run-with-idle-timer 2 t (lambda () (garbage-collect)))

would now run

(setq gc-cons-threshold (eval-when-compile (* 1024 1024 1024)))
(run-with-idle-timer 2 t (lambda () (garbage-collect-and-trim)))

instead.

martin





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 15:16:02 GMT) Full text and rfc822 format available.

Message #152 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 10:15:11 -0500
> Stefan, what do you think? Will it be okay if I implement a patch that runs
> `malloc_trim(0)` when Emacs is idle?

That's yet another reason why we should provide that function to ELisp,
and then have ELisp decide when it's called (whether after GC, or on
idle or what).


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 15:16:03 GMT) Full text and rfc822 format available.

Message #155 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, Eli Zaretskii <eliz <at> gnu.org>,
 dj <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 10:15:17 -0500
> Upside indeed is the memory reduction.

I expect so, but the measurement is the thing we need here.
How much is the memory reduced (in the case where the GC vars are left
to their default value)?

> Well, I didn't send the patches for my only benefit, but for benefit of
> others people.  The new ELisp function is something that not too many people
> would benefit from, and I mean, including those who disable GC.  That is
> because it would be an opt-in feature, which you need to know about to
> enable it, and not many will ever find out about it.

If it's very useful even with the default GC settings, then there's
a good reason to say it should be enabled by default, but if not then
I'd expect that those people who set their GC vars manually will learn
to complete their GC settings by adding that function to their
`post-gc-hook`.

> For my-only benefit I could just continue building Emacs with my patch
> applied locally, as I do now.

Yes, I have my share of local patches as well ;-)
But I think there's a good case to be made that it can benefit others,


        Stefan


PS: BTW, we can arbitrarily reduce the percentage of CPU time spent in
malloc_trim by only calling it every N times rather than after every GC.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 15:30:02 GMT) Full text and rfc822 format available.

Message #158 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 18:29:41 +0300
On Wed, 2021-02-03 at 10:15 -0500, Stefan Monnier wrote:
> > Stefan, what do you think? Will it be okay if I implement a patch that runs
> > `malloc_trim(0)` when Emacs is idle?
> 
> That's yet another reason why we should provide that function to ELisp,
> and then have ELisp decide when it's called (whether after GC, or on
> idle or what).

Okay, let's discuss this idea. It seems that running `malloc_trim(0)` on idle (let's say, after 10 seconds of idling, which implies a user might have switch to a browser, or something) should resolve all performance concerns. Especially given, measurements show it has pretty negligible impact even when located on return from GC.

To answer you question in another email about memory benefits given default Emacs settings: well, today I tried creating a testcase that would reproduce problem with default settings, but haven't really succeeded at it. I have a testcase where Emacs without the patch has ≈20M more memory than the one with the patch, but that's pretty small difference, and offhand I didn't manage to get it increased any further.

So, I'm thinking of wiring the functional of memory trimming to on-idle hook, without possibility to disable it. Given how small performance impact in this case would be, I see no reason to even implement an option to disable it.

Thoughts?





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 16:03:02 GMT) Full text and rfc822 format available.

Message #161 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 11:02:22 -0500
> To answer you question in another email about memory benefits given default
> Emacs settings: well, today I tried creating a testcase that would reproduce
> problem with default settings, but haven't really succeeded at it.  I have
> a testcase where Emacs without the patch has ≈20M more memory than the one
> with the patch, but that's pretty small difference, and offhand I didn't
> manage to get it increased any further.

Thanks.  At least that seems to indicate that glibc does its job
properly for the way we normally use it.

> So, I'm thinking of wiring the functional of memory trimming to on-idle
> hook, without possibility to disable it.

That seems hard to do (luckily), since AFAICT idle hooks only exist via
`run-with-idle-timer` and those can always be disabled with things like
`cancel-timer`.

> Given how small performance impact in this case would be, I see no
> reason to even implement an option to disable it.
> Thoughts?

My main thought is that if `malloc_trim` indeed makes a significant
difference, it's a sign that Emacs's own code did its job (it called
`free` as it should) and that the problem is in how glibc decided not
to return the memory to the OS.

That's a behavior that can (and will) change over time outside of
our control.  So calling `malloc_trim` every time I stop typing for 10s,
just on account of "maybe glibc didn't reclaim quite as much memory as
we'd like this time" doesn't sound very appealing to me.

It sounds like an ad-hoc quick hack.  I love being able to use ad-hoc
quick hacks, but I don't like enabling such things by default when the
only use-cases where they're known to be useful are fairly specialized
(and discouraged by Emacs maintainers ;-)

So I think we need more info: do the glibc maintainers consider it
normal for glibc to behave this way?  Why does it behave this way?
Would the equivalent of `malloc_trim` happen anyway "at some point in
the future"?  E.g. If you create a test case where you disable GC, let
the memory use grow to 1GB, then reset the GC vars to their default and
keep using Emacs modestly, will the memory ever be returned to the OS or
is an explicit call to `malloc_trim` really indispensable?

But until we get all the answers to these questions, we can already
install the code that exposes `malloc_trim` to ELisp.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 16:36:01 GMT) Full text and rfc822 format available.

Message #164 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 19:35:08 +0300
On Wed, 2021-02-03 at 11:02 -0500, Stefan Monnier wrote:
> > To answer you question in another email about memory benefits given default
> > Emacs settings: well, today I tried creating a testcase that would reproduce
> > problem with default settings, but haven't really succeeded at it.  I have
> > a testcase where Emacs without the patch has ≈20M more memory than the one
> > with the patch, but that's pretty small difference, and offhand I didn't
> > manage to get it increased any further.
>
> Thanks.  At least that seems to indicate that glibc does its job
> properly for the way we normally use it.
>
> > So, I'm thinking of wiring the functional of memory trimming to on-idle
> > hook, without possibility to disable it.
>
> That seems hard to do (luckily), since AFAICT idle hooks only exist via
> `run-with-idle-timer` and those can always be disabled with things like
> `cancel-timer`.

Ah, okay then. I just didn't know how on-idle code should be implemented; if it would
be just making a ELisp wrapper and adding it to the hook, which people can then
remove if they want to, that's fine. I just thought there's some additional work
required to make it "disableable", I'm not opposed to the idea of it being so per se.

> > Given how small performance impact in this case would be, I see no
> > reason to even implement an option to disable it.
> > Thoughts?
>
> My main thought is that if `malloc_trim` indeed makes a significant
> difference, it's a sign that Emacs's own code did its job (it called
> `free` as it should) and that the problem is in how glibc decided not
> to return the memory to the OS.
>
> That's a behavior that can (and will) change over time outside of
> our control.  So calling `malloc_trim` every time I stop typing for 10s,
> just on account of "maybe glibc didn't reclaim quite as much memory as
> we'd like this time" doesn't sound very appealing to me.
>
> It sounds like an ad-hoc quick hack.  I love being able to use ad-hoc
> quick hacks, but I don't like enabling such things by default when the
> only use-cases where they're known to be useful are fairly specialized
> (and discouraged by Emacs maintainers ;-)

I totally agree with you, and I too consider it a hack.

> So I think we need more info: do the glibc maintainers consider it
> normal for glibc to behave this way?  Why does it behave this way?

Very good question! I hope Glibc mainainers that are on CC list will be able to
answer. Even though I created a report on Glibc just some months ago, the problem per
se existed for a long time. And I've seen Carlos O'Donell leaving a small comment on a
similar issue with Ruby 2 years ago, which implies they're aware of this situation.

> Would the equivalent of `malloc_trim` happen anyway "at some point in
> the future"?  E.g. If you create a test case where you disable GC, let
> the memory use grow to 1GB, then reset the GC vars to their default and
> keep using Emacs modestly, will the memory ever be returned to the OS or
> is an explicit call to `malloc_trim` really indispensable?

No, the memory will never be returned to OS. I can tell that right away, because the
only difference would be `free()` getting called more often.

I think it is worth mentioning here that Glibc usually does return memory to the OS
without any need in malloc_trim(0). What happens in affected applications (such as
here) is that an application stumbles upon a very special allocation pattern, which
kinda breaks Glibc algorithms of returning memory.

That's btw to the point of whether this GLibc behavior is a bug: well, sometimes it
works, sometimes it doesn't — doesn't look like purposeful behavior to me :)

> But until we get all the answers to these questions, we can already
> install the code that exposes `malloc_trim` to ELisp.
>
>
>         Stefan
>






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 16:53:02 GMT) Full text and rfc822 format available.

Message #167 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 11:51:55 -0500
>> So I think we need more info: do the glibc maintainers consider it
>> normal for glibc to behave this way?  Why does it behave this way?
> Very good question! I hope Glibc mainainers that are on CC list will be able to
> answer.  Even though I created a report on Glibc just some months ago, the problem per
> se existed for a long time. And I've seen Carlos O'Donell leaving a small comment on a
> similar issue with Ruby 2 years ago, which implies they're aware of this situation.

I mean, I understand why glibc doesn't always immediately release memory
to the OS, but I'd like to better understand whether we can expect that
there is a mechanism in glibc to avoid it keeping 500MB of free memory
around eternally when the subsequent actual use remains below 100MB.

>> Would the equivalent of `malloc_trim` happen anyway "at some point in
>> the future"?  E.g. If you create a test case where you disable GC, let
>> the memory use grow to 1GB, then reset the GC vars to their default and
>> keep using Emacs modestly, will the memory ever be returned to the OS or
>> is an explicit call to `malloc_trim` really indispensable?
>
> No, the memory will never be returned to OS. I can tell that right
> away, because the only difference would be `free()` getting called
> more often.

I'm not sure I follow: if I were to implement a malloc library, calls to
`free` would be exactly the place where I'd decide that some memory
should be returned to the OS, so even if a given call to `free` might
not return the now-unused 400MB, I'd expect that this memory might be
finally returned after some number of other/unrelated calls to `free`.

> I think it is worth mentioning here that Glibc usually does return
> memory to the OS without any need in malloc_trim(0). What happens in
> affected applications (such as here) is that an application stumbles
> upon a very special allocation pattern, which kinda breaks Glibc
> algorithms of returning memory.

Indeed.  The question is whether it's a bug in glibc or whether it's
something that the upper layer should deal with.  Knowing a bit better
why/when this happens would also help the upper layer decide when to
call `malloc_trim` if indeed that's needed (another useful info would be
a function that returns the mount of memory there is to trim, assuming
that info can be obtained much more cheaply than a call to
`malloc_trim`).


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 19:26:01 GMT) Full text and rfc822 format available.

Message #170 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at,
 monnier <at> iro.umontreal.ca, hi-angel <at> yandex.ru, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 14:25:15 -0500
Eli Zaretskii <eliz <at> gnu.org> writes:
>> The problem we're dealing here with is an actual bug in glibc⁵. What
>> this implies is that if the fix indeed hurts performance someplace,
>> well, then it's that this place requires additional
>> performance-related fixes. As opposed to just ignoring the bug
>> because of performance got somewhere decreased. Things like, changing
>> the slow algorithm, or modifying GC behavior for specific usecases…
>
> The fact that the bug you reported didn't get any responses in  more
> than a month, let alone wasn't fixed, could be a sign that not
> everyone agrees this is a bug...

Right, glibc's malloc maintains a cache of re-usable chunks of memory,
for performance reasons.  That cache, obviously, costs memory.
malloc_trim() flushes that cache and returns memory to the kernel.  That
has two effects: first, your memory footprint is smaller, but second,
your performance will suffer until the cache is refilled.

We (glibc devs) don't consider "poor cache performance for my
application" to be a bug.  A patch which improves cache performance *for
most apps* would be considered, but a patch that improves one app's
speed at the cost of most other apps, would be rejected.

You (emacs devs) need to decide whether you care more about memory
footprint or memory performance, and tune malloc accordingly.
malloc_trim() is one knob to tune, there are others.  But don't say it's
a "bug" if our defaults don't match your optimal settings.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 19:32:02 GMT) Full text and rfc822 format available.

Message #173 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, rudalics <at> gmx.at, fweimer <at> redhat.com,
 45200 <at> debbugs.gnu.org, hi-angel <at> yandex.ru
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 14:30:56 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> I'm not sure I follow: if I were to implement a malloc library, calls to
> `free` would be exactly the place where I'd decide that some memory
> should be returned to the OS,

Heh.  malloc() and free() are on the hot path for many time-critical
things; if you wasted time in free() when you didn't have to, people
would complain.  *This* is the tradeoff we (glibc devs) have to make -
performance vs footprint.  Gaining even a few percent in a malloc/free
benchmark is a *huge* win for some folks.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 19:37:02 GMT) Full text and rfc822 format available.

Message #176 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, rudalics <at> gmx.at, fweimer <at> redhat.com,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 14:36:05 -0500
Konstantin Kharlamov <hi-angel <at> yandex.ru> writes:
>> So I think we need more info: do the glibc maintainers consider it
>> normal for glibc to behave this way?  Why does it behave this way?
>
> Very good question! I hope Glibc mainainers that are on CC list will be able to
> answer.

The answers are "yes" and "performance".  Sorry.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 19:51:01 GMT) Full text and rfc822 format available.

Message #179 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: DJ Delorie <dj <at> redhat.com>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at,
 monnier <at> iro.umontreal.ca, hi-angel <at> yandex.ru, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 21:49:54 +0200
> From: DJ Delorie <dj <at> redhat.com>
> Cc: hi-angel <at> yandex.ru, rudalics <at> gmx.at, monnier <at> iro.umontreal.ca,
>         carlos <at> redhat.com, fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
> Date: Wed, 03 Feb 2021 14:25:15 -0500
> 
> You (emacs devs) need to decide whether you care more about memory
> footprint or memory performance, and tune malloc accordingly.
> malloc_trim() is one knob to tune, there are others.

Which other knobs are there that aren't deprecated and could disappear
without a warning, though?  We used to use some knobs in the past,
then one day we were told we should stop because those knobs will no
longer be available.

We still use some knobs (see alloc.c), but could some of you please
review that and see if the optimizations we attempt through those
knobs are reasonable?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 20:25:01 GMT) Full text and rfc822 format available.

Message #182 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: DJ Delorie <dj <at> redhat.com>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 Eli Zaretskii <eliz <at> gnu.org>, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 15:24:23 -0500
DJ Delorie [2021-02-03 14:25:15] wrote:
> Right, glibc's malloc maintains a cache of re-usable chunks of memory,
> for performance reasons.

Right, so far as good.

> We (glibc devs) don't consider "poor cache performance for my
> application" to be a bug.  A patch which improves cache performance *for
> most apps* would be considered, but a patch that improves one app's
> speed at the cost of most other apps, would be rejected.

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.

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.
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".

So what causes Emacs's experience to be different?
If I read `mallopt`s man page carefully I see it say:

       M_TRIM_THRESHOLD
              When the amount of contiguous free memory at the top of the heap
              grows  sufficiently  large,  free(3)  employs sbrk(2) to release
              this memory back to the system.  (This can be useful in programs

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

If so, it does seem like a weakness of glibc's heuristic.

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

> You (emacs devs) need to decide whether you care more about memory
> footprint or memory performance, and tune malloc accordingly.
> malloc_trim() is one knob to tune, there are others.  But don't say it's
> a "bug" if our defaults don't match your optimal settings.

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.

I suspect the issue is how to make it so the malloc library can keep
track of the size of the "cache" without slowing down the most common
execution path.  Once that is done, it should be easy to check the size
of the "cache" every once in a while (e.g. when requesting more memory
from the OS) and call malloc_trim when that cache is "way too big".
Tho of course, "way too big" might just mean we're just about to
re-allocate it, so we'd probably want to include some notion of time so
we only call `malloc_trim` if it's been "way too big" for a while.


        Stefan






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 20:30:02 GMT) Full text and rfc822 format available.

Message #185 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: DJ Delorie <dj <at> redhat.com>
Cc: carlos <at> redhat.com, rudalics <at> gmx.at, fweimer <at> redhat.com,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 23:28:54 +0300
On Wed, 2021-02-03 at 14:36 -0500, DJ Delorie wrote:
> Konstantin Kharlamov <hi-angel <at> yandex.ru> writes:
> > > So I think we need more info: do the glibc maintainers consider it
> > > normal for glibc to behave this way?  Why does it behave this way?
> > 
> > Very good question! I hope Glibc mainainers that are on CC list will be able
> > to
> > answer.
> 
> The answers are "yes" and "performance".  Sorry.
> 

Thanks for chiming in. Let me rephrase a question of mine: right now, Glibc behaves in an odd way:

α) sometimes, call to `free()` frees memory completely
β) sometimes, call to `free()` leaves memory lingering forever, till malloc_trim is called additionally.

The answer I'd like to know is why do you not do always either α or always β? (I'm leaving out here the question of which way is correct and why, I'm rather curious just why the difference in behavior).





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 20:43:02 GMT) Full text and rfc822 format available.

Message #188 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 15:42:11 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> 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.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 20:53:01 GMT) Full text and rfc822 format available.

Message #191 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, rudalics <at> gmx.at, fweimer <at> redhat.com,
 monnier <at> iro.umontreal.ca, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 15:51:51 -0500
Konstantin Kharlamov <hi-angel <at> yandex.ru> writes:
> α) sometimes, call to `free()` frees memory completely
> β) sometimes, call to `free()` leaves memory lingering forever, till malloc_trim is called additionally.
>
> The answer I'd like to know is why do you not do always either α or
> always β? (I'm leaving out here the question of which way is correct
> and why, I'm rather curious just why the difference in behavior).

If the chunk being free'd happens to be the highest-addressed chunk in
the heap, it "exposes" that hole in the heap below it, if that exceeds
MALLOC_TRIM_THRESHOLD it causes a trim.

If the chunk is *not* at the top of the heap, nothing happens.  We only
trim the top of the heap.

Of course, this assumes that the caching logic doesn't decide to hold on
to the chunk *anyway* (like, if it's put in tcache), in which case it's
not freed despite being at the top of the heap.  Note that any patch
affecting tcache performance will need to be vigorously defended ;-)

IIRC the fastbin cache also holds onto the top chunk.  Since trimming
cleans the fastbin, this often frees the top chunk.  Disabling fastbins
might be an interesting thing to try.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 21:02:02 GMT) Full text and rfc822 format available.

Message #194 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at,
 monnier <at> iro.umontreal.ca, hi-angel <at> yandex.ru, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 16:00:38 -0500
Eli Zaretskii <eliz <at> gnu.org> writes:
> Which other knobs are there that aren't deprecated and could disappear
> without a warning, though?  We used to use some knobs in the past,
> then one day we were told we should stop because those knobs will no
> longer be available.

There's a whole section in the glibc manual on "Memory Allocation
Tunables", which is the "new" way to do this.

"man mallopt" is the other way.

Using these you could, for example, disable the tcache and fastbins
completely and see how that works for you.  Or limit the number of
arenas.  Or let smaller allocations go directly to mmap().

There are some environment variables which affect malloc, but we're
trying to get rid of those.

Maybe in ten or twenty years we'll come up with some better way, but
that's the future's problem ;-)





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 22:08:02 GMT) Full text and rfc822 format available.

Message #197 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: DJ Delorie <dj <at> redhat.com>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 17:07:04 -0500
>> 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

I'm not worried about the absolute value, but about the proportion.
I think in memory management code, having an overall overhead of 50% is
generally considered acceptable (i.e. actual memory allocated is twice
the memory used by the application), whether that comes from
internal&external fragmentation or a stop&copy GC, ...

But in our specific use case, there seems to be no limit to the
overhead: if the application uses a heap of size N at some point in time
it will never grown back down, so the overhead can end up being
arbitrarily large.

> *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.

If the average allocation/deallocation rate justifies it, I fully agree.
But if the variation of allocated space stays well below that for a long
time, then those 200MB are truly wasted.

>> 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?

I haven't thought very much about it, so I'm sure it's easy to shoot
holes through it, but I imagined something like:

- one `static unsigned long hoard_size` keeps the approximate amount of
  space that is free but not returned to the OS.
  Not sure where/when to keep it up to date cheaply, admittedly.

- one `static unsigned long smallest_recent_hoard_size`.
  This is updated whenever we allocate memory from the OS.

- one `static unsigned long age_of_smallest_recent_hoard_size`.
  This is incremented every time we allocate memory from the OS (and
  reset whenever the value of smallest_recent_hoard_size is modified).

Then you'd call `malloc_trim` based on a magic formula combining
`age_of_smallest_recent_hoard_size` and the ratio of
`smallest_recent_hoard_size / total_heap_size` (and you'd trim only
what's necessary to release O(`smallest_recent_hoard_size`) memory).

> Yet another word of memory used,

Since 200MB is peanuts, I figure that extra 24B should be acceptable ;-)

> yet another syscall to check the time?

I didn't mean time as in an OS-notion of clock, no.

> 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.

No doubt.

> 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.

Delaying for some time is one thing.  Delaying forever is another.

>> 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".

Ah, I see, that makes sense.
I do remember such behavior in other/older libc libraries.

> We used to have code that munmap()'d large "holes" in the cache,

That's what I seem to remember, indeed.  And our memory management code
does play with `mallopt` in the hopes to encourage it to allocate using
`mmap` in the hopes that it then deallocates via `munmap`.

> but the resulting performance was horrible.

Hmm... so that explains why we're seeing those problems again.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 22:22:01 GMT) Full text and rfc822 format available.

Message #200 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 17:21:44 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> I haven't thought very much about it, so I'm sure it's easy to shoot
> holes through it, but I imagined something like:

A bit of devil's advocacy just for giggles...

> - one `static unsigned long hoard_size` keeps the approximate amount of
>   space that is free but not returned to the OS.
>   Not sure where/when to keep it up to date cheaply, admittedly.

With full atomic access because malloc is multi-threaded; atomics are
expensive compared to thread-local or nonexisting data.  Updating this
has to be in the critical path, too.

> - one `static unsigned long smallest_recent_hoard_size`.
>   This is updated whenever we allocate memory from the OS.

We map huge chunks at a time, but they stay unbacked until they're
actually used.

> Then you'd call `malloc_trim` based on a magic formula

That's cheating ;-)

>> Yet another word of memory used,
>
> Since 200MB is peanuts, I figure that extra 24B should be acceptable ;-)

*per chunk*.  You allocate 1 byte and you get 32 at the moment, because
of these lower limits.  We're already getting complaints about this
particular overhead.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 03 Feb 2021 23:33:02 GMT) Full text and rfc822 format available.

Message #203 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: DJ Delorie <dj <at> redhat.com>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 18:32:36 -0500
>> - one `static unsigned long hoard_size` keeps the approximate amount of
>>   space that is free but not returned to the OS.
>>   Not sure where/when to keep it up to date cheaply, admittedly.
> With full atomic access because malloc is multi-threaded; atomics are
> expensive compared to thread-local or nonexisting data.  Updating this
> has to be in the critical path, too.

Indeed, multithreading makes it all much more fun.  I guess you'd want
to make those info thread-local, which would force a rethink of its
definition (what about data allocated in one thread bu freed in another,
yadda, yadda).  The key would be to make sure this is not updated for
every call to `free` but only for some of them (that's why it says
"approximate").

Not having the source code of `free` at hand, I'm free to assume that
this is possible.  E.g. we could say that we don't count objects smaller
than a certain size or for objects smaller than 2^N (for some arbitrary
2^N), you only count it if it's placed at the beginning of the 2^N chunk
(and you count it as having size 2^N)?

>> - one `static unsigned long smallest_recent_hoard_size`.
>>   This is updated whenever we allocate memory from the OS.
> We map huge chunks at a time, but they stay unbacked until they're
> actually used.

By "whenever we allocate memory from the OS" I really meant "in a code
path that's not speed critical but which can be expected to be executed
eventually".  Maybe there isn't any such path except for those that may
never be executed?

>> Then you'd call `malloc_trim` based on a magic formula
> That's cheating ;-)

Like the rest of my hand waving wasn't?
C'mon, give me some credit!

[ Just to clarify: by "magic formula" I meant that this would be the
  part amenable to tuning to decide how often we're willing to pay for
  `malloc_trim`.  ]

>>> Yet another word of memory used,
>> Since 200MB is peanuts, I figure that extra 24B should be acceptable ;-)
> *per chunk*.

No, those counters are meant to be global.  

Anyway.  I see that we should presume that our glibc will not release
our memory back to the OS unless we explicitly ask it to with
`malloc_trim`.  Thanks.

One thing that remains a bit unclear for me is in the doc of
`malloc_trim`; it says:

       The pad argument specifies the amount of free space to leave  untrimmed
       at the top of the heap.  If this argument is 0, only the minimum amount
       of memory is maintained at the top of  the  heap  (i.e.,  one  page  or
       less).   A nonzero argument can be used to maintain some trailing space
       at the top of the heap in order to allow future allocations to be  made
       without having to extend the heap with sbrk(2).

But this only talks about the free space at the "top".  Since in our
case most of the free space is not at the top, I wonder:
say we have 64KB free at the top and 64MB free elsewhere and we call
`malloc_trim` with a `pad` of 16MB, will it release ~48MB of the
non-top free memory or will it free all 64MB of the non-top free memory
or ... ?


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 00:33:01 GMT) Full text and rfc822 format available.

Message #206 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 19:31:56 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>>>> Yet another word of memory used,
>>> Since 200MB is peanuts, I figure that extra 24B should be acceptable ;-)
>> *per chunk*.
>
> No, those counters are meant to be global.  

To clarify, that extra word was the "chunk age" information, not the
aggregate metrics.

> One thing that remains a bit unclear for me is in the doc of
> `malloc_trim`; it says:
>
>        The pad argument specifies the amount of free space to leave  untrimmed
>        at the top of the heap.  If this argument is 0, only the minimum amount
>        of memory is maintained at the top of  the  heap  (i.e.,  one  page  or
>        less).   A nonzero argument can be used to maintain some trailing space
>        at the top of the heap in order to allow future allocations to be  made
>        without having to extend the heap with sbrk(2).
>
> But this only talks about the free space at the "top".  Since in our
> case most of the free space is not at the top, I wonder:
> say we have 64KB free at the top and 64MB free elsewhere and we call
> `malloc_trim` with a `pad` of 16MB, will it release ~48MB of the
> non-top free memory or will it free all 64MB of the non-top free memory
> or ... ?

No.  Even the tiniest allocation still in use at the top of the heap
locks the entire rest of the heap into memory.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 03:27:05 GMT) Full text and rfc822 format available.

Message #209 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: DJ Delorie <dj <at> redhat.com>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 22:26:29 -0500
>> But this only talks about the free space at the "top".  Since in our
>> case most of the free space is not at the top, I wonder:
>> say we have 64KB free at the top and 64MB free elsewhere and we call
>> `malloc_trim` with a `pad` of 16MB, will it release ~48MB of the
>> non-top free memory or will it free all 64MB of the non-top free memory
>> or ... ?
>
> No.  Even the tiniest allocation still in use at the top of the heap
> locks the entire rest of the heap into memory.

Hmm... then I don't understand: the user who reports the problem with
Emacs claims that calling `malloc_trim` reduces the PSS size of
Emacs tremendously (from 260MB down to 60MB).

If `malloc_trim` can't release memory other than at the top, then how
come glibc didn't recover those 200MB on its own (e.g. it seems 200MB
is well beyond the default value of M_TRIM_THRESHOLD)?



        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 03:39:01 GMT) Full text and rfc822 format available.

Message #212 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 22:38:04 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> No.  Even the tiniest allocation still in use at the top of the heap
>> locks the entire rest of the heap into memory.
>
> Hmm... then I don't understand: the user who reports the problem with
> Emacs claims that calling `malloc_trim` reduces the PSS size of
> Emacs tremendously (from 260MB down to 60MB).
>
> If `malloc_trim` can't release memory other than at the top, then how
> come glibc didn't recover those 200MB on its own (e.g. it seems 200MB
> is well beyond the default value of M_TRIM_THRESHOLD)?

Well, let me make up a case that "works" and you tell me if this is
common in emacs.

Consider you've spent the day doing normal things and your heap is at
100 Mb.  Now you do something memory-intensive for a few minutes, and
stop, and gc runs.  That "something" allocates a lot of memory, but it's
all going to be at the top of the heap - aside from whatever fits in the
first 100 Mb.  It's all released, and GC free()'s it all.  malloc_trim()
at this point would coalesce it and return it to the system.

As long as gc runs between each type of "task", a high-memory task will
be trimmable because GC would have freed all that memory and it's all
together at the top of the heap.

What would cause a problem is, say, if in the middle of running a high
memory task you *also* load a font or something and *that* locks the top
of the heap.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 03:56:01 GMT) Full text and rfc822 format available.

Message #215 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: DJ Delorie <dj <at> redhat.com>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 22:55:25 -0500
>>> No.  Even the tiniest allocation still in use at the top of the heap
>>> locks the entire rest of the heap into memory.
>>
>> Hmm... then I don't understand: the user who reports the problem with
>> Emacs claims that calling `malloc_trim` reduces the PSS size of
>> Emacs tremendously (from 260MB down to 60MB).
>>
>> If `malloc_trim` can't release memory other than at the top, then how
>> come glibc didn't recover those 200MB on its own (e.g. it seems 200MB
>> is well beyond the default value of M_TRIM_THRESHOLD)?
>
> Well, let me make up a case that "works" and you tell me if this is
> common in emacs.
>
> Consider you've spent the day doing normal things and your heap is at
> 100 Mb.  Now you do something memory-intensive for a few minutes, and
> stop, and gc runs.  That "something" allocates a lot of memory, but it's
> all going to be at the top of the heap - aside from whatever fits in the
> first 100 Mb.  It's all released, and GC free()'s it all.  malloc_trim()
> at this point would coalesce it and return it to the system.

But wouldn't glibc release that memory even without calling
`malloc_trim` simply because it's at the top and is larger than
`M_TRIM_THRESHOLD`?


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 04:03:02 GMT) Full text and rfc822 format available.

Message #218 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 23:02:05 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> But wouldn't glibc release that memory even without calling
> `malloc_trim` simply because it's at the top and is larger than
> `M_TRIM_THRESHOLD`?

Probably, if you disabled fastbins.  Like I said earler, I think
fastbins bypasses the top-of-heap consolidation, so the chunks might be
free'd but in the fastbin cache.  malloc_trim() flushes the fastbin
cache.

There are other ways to flush the fastbins but they're harder to
programmatically invoke (i.e. "magic rules").





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 04:05:01 GMT) Full text and rfc822 format available.

Message #221 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 23:04:14 -0500
Also, fastbins bypass the chunk consolidation, so even if all the memory
is free()'d it might still be in small-chunk form in the fastbins, ready
for fast re-use.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 04:20:01 GMT) Full text and rfc822 format available.

Message #224 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: DJ Delorie <dj <at> redhat.com>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 23:19:40 -0500
>> But wouldn't glibc release that memory even without calling
>> `malloc_trim` simply because it's at the top and is larger than
>> `M_TRIM_THRESHOLD`?
> Probably, if you disabled fastbins.  Like I said earler, I think
> fastbins bypasses the top-of-heap consolidation, so the chunks might be
> free'd but in the fastbin cache.  malloc_trim() flushes the fastbin
> cache.
> There are other ways to flush the fastbins but they're harder to
> programmatically invoke (i.e. "magic rules").
> Also, fastbins bypass the chunk consolidation, so even if all the memory
> is free()'d it might still be in small-chunk form in the fastbins, ready
> for fast re-use.

[ I have no idea what "fastbins" are, but I'll nod along approvingly.  ]

OK, so `malloc_trim` can do a more thorough job and discover that
there's indeed 200MB free at the top which malloc/free wouldn't
have noticed?  I guess that makes sense.

Since our GC doesn't move objects, there will often be some left over
live object near the top that will prevent most of those mythical 200MB
from being released.

Anyway, thanks for bearing with us and hand-holding me until I start to
feel like I understand the situation.
I have a much better understanding of what Emacs might be able to do.


        Stefan


PS: One last thing: I must say I'm surprised to see the amount of effort
that seems to be spent on trying to release that "top" free memory.
From where I stand, it seems that it will only very rarely allow you to
release any non-trivial amount of memory.  Why bother?





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Thu, 04 Feb 2021 04:27:01 GMT) Full text and rfc822 format available.

Message #227 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: DJ Delorie <dj <at> redhat.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, carlos <at> redhat.com, rudalics <at> gmx.at, hi-angel <at> yandex.ru,
 eliz <at> gnu.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 03 Feb 2021 23:26:45 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> [ I have no idea what "fastbins" are, but I'll nod along approvingly.  ]

https://sourceware.org/glibc/wiki/MallocInternals

Fastbins are one of the caches layered on the core malloc code.

> OK, so `malloc_trim` can do a more thorough job and discover that
> there's indeed 200MB free at the top which malloc/free wouldn't
> have noticed?  I guess that makes sense.

Yes.

> PS: One last thing: I must say I'm surprised to see the amount of
> effort that seems to be spent on trying to release that "top" free
> memory.  From where I stand, it seems that it will only very rarely
> allow you to release any non-trivial amount of memory.  Why bother?

We have to keep track of the top of heap anyway, in order to grow it.
Adding a check to shrink it is pretty trivial, and it's our *only* way
to return memory to the system.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Tue, 18 May 2021 20:14:01 GMT) Full text and rfc822 format available.

Message #230 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Tue, 18 May 2021 23:12:53 +0300
Okay, apparently I'm not the only one affected by the memory problem¹, so I'll
try to make the necessary change for it to go over the finish line.

I have a question though. So, wrapping `malloc_trim` in elisp and adding it to
idle with `(run-with-idle-timer)` sounds simple. But, where in code should I do
the `(run-with-idle-timer)` call, i.e. so it's called as is emacs is getting
initialized?

1:
https://www.reddit.com/r/emacs/comments/n13v5l/what_is_the_next_big_feature_after_native_comp/gwc5g77/?context=3

On Wed, 2021-02-03 at 11:02 -0500, Stefan Monnier wrote:
> > To answer you question in another email about memory benefits given default
> > Emacs settings: well, today I tried creating a testcase that would reproduce
> > problem with default settings, but haven't really succeeded at it.  I have
> > a testcase where Emacs without the patch has ≈20M more memory than the one
> > with the patch, but that's pretty small difference, and offhand I didn't
> > manage to get it increased any further.
> 
> Thanks.  At least that seems to indicate that glibc does its job
> properly for the way we normally use it.
> 
> > So, I'm thinking of wiring the functional of memory trimming to on-idle
> > hook, without possibility to disable it.
> 
> That seems hard to do (luckily), since AFAICT idle hooks only exist via
> `run-with-idle-timer` and those can always be disabled with things like
> `cancel-timer`.
> 
> > Given how small performance impact in this case would be, I see no
> > reason to even implement an option to disable it.
> > Thoughts?
> 
> My main thought is that if `malloc_trim` indeed makes a significant
> difference, it's a sign that Emacs's own code did its job (it called
> `free` as it should) and that the problem is in how glibc decided not
> to return the memory to the OS.
> 
> That's a behavior that can (and will) change over time outside of
> our control.  So calling `malloc_trim` every time I stop typing for 10s,
> just on account of "maybe glibc didn't reclaim quite as much memory as
> we'd like this time" doesn't sound very appealing to me.
> 
> It sounds like an ad-hoc quick hack.  I love being able to use ad-hoc
> quick hacks, but I don't like enabling such things by default when the
> only use-cases where they're known to be useful are fairly specialized
> (and discouraged by Emacs maintainers ;-)
> 
> So I think we need more info: do the glibc maintainers consider it
> normal for glibc to behave this way?  Why does it behave this way?
> Would the equivalent of `malloc_trim` happen anyway "at some point in
> the future"?  E.g. If you create a test case where you disable GC, let
> the memory use grow to 1GB, then reset the GC vars to their default and
> keep using Emacs modestly, will the memory ever be returned to the OS or
> is an explicit call to `malloc_trim` really indispensable?
> 
> But until we get all the answers to these questions, we can already
> install the code that exposes `malloc_trim` to ELisp.
> 
> 
>         Stefan
> 






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 04:12:01 GMT) Full text and rfc822 format available.

Message #233 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 19 May 2021 00:11:32 -0400
> Okay, apparently I'm not the only one affected by the memory problem¹, so I'll
> try to make the necessary change for it to go over the finish line.

Sadly, malloc_trim does not satisfy the request "a GC that actually
releases the memory back to the system": we do release it back to glibc
but glibc only does it when we're lucky enough that the memory we
released is all at the very end of the heap (and that constraint
apparently also applies to `mallov_trim`).

A concurrent GC would be great, yes.  XEmacs had that, pretty much (not
concurrent, only incremental, but it should not be terribly hard to
push it over the edge and make it concurrent).

> I have a question though. So, wrapping `malloc_trim` in elisp and adding it to
> idle with `(run-with-idle-timer)` sounds simple. But, where in code should I do
> the `(run-with-idle-timer)` call, i.e. so it's called as is emacs is getting
> initialized?

I'd oppose calling `malloc-trim` in the default config.  So the answer
would be "in your ~/.emacs" (presumably next to the code that changes
the GC config vars ;-)


        Stefan


>
> 1:
> https://www.reddit.com/r/emacs/comments/n13v5l/what_is_the_next_big_feature_after_native_comp/gwc5g77/?context=3
>
> On Wed, 2021-02-03 at 11:02 -0500, Stefan Monnier wrote:
>> > To answer you question in another email about memory benefits given default
>> > Emacs settings: well, today I tried creating a testcase that would reproduce
>> > problem with default settings, but haven't really succeeded at it.  I have
>> > a testcase where Emacs without the patch has ≈20M more memory than the one
>> > with the patch, but that's pretty small difference, and offhand I didn't
>> > manage to get it increased any further.
>> 
>> Thanks.  At least that seems to indicate that glibc does its job
>> properly for the way we normally use it.
>> 
>> > So, I'm thinking of wiring the functional of memory trimming to on-idle
>> > hook, without possibility to disable it.
>> 
>> That seems hard to do (luckily), since AFAICT idle hooks only exist via
>> `run-with-idle-timer` and those can always be disabled with things like
>> `cancel-timer`.
>> 
>> > Given how small performance impact in this case would be, I see no
>> > reason to even implement an option to disable it.
>> > Thoughts?
>> 
>> My main thought is that if `malloc_trim` indeed makes a significant
>> difference, it's a sign that Emacs's own code did its job (it called
>> `free` as it should) and that the problem is in how glibc decided not
>> to return the memory to the OS.
>> 
>> That's a behavior that can (and will) change over time outside of
>> our control.  So calling `malloc_trim` every time I stop typing for 10s,
>> just on account of "maybe glibc didn't reclaim quite as much memory as
>> we'd like this time" doesn't sound very appealing to me.
>> 
>> It sounds like an ad-hoc quick hack.  I love being able to use ad-hoc
>> quick hacks, but I don't like enabling such things by default when the
>> only use-cases where they're known to be useful are fairly specialized
>> (and discouraged by Emacs maintainers ;-)
>> 
>> So I think we need more info: do the glibc maintainers consider it
>> normal for glibc to behave this way?  Why does it behave this way?
>> Would the equivalent of `malloc_trim` happen anyway "at some point in
>> the future"?  E.g. If you create a test case where you disable GC, let
>> the memory use grow to 1GB, then reset the GC vars to their default and
>> keep using Emacs modestly, will the memory ever be returned to the OS or
>> is an explicit call to `malloc_trim` really indispensable?
>> 
>> But until we get all the answers to these questions, we can already
>> install the code that exposes `malloc_trim` to ELisp.
>> 
>> 
>>         Stefan
>> 





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 04:27:02 GMT) Full text and rfc822 format available.

Message #236 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 19 May 2021 00:26:04 -0400
> I'd oppose calling `malloc-trim` in the default config.

BTW, to clarify, I'd oppose it based on the current data we have.  If we
can collect data that shows it to be sufficiently useful for the default
config, then of course, I'd have no objection,


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 06:47:02 GMT) Full text and rfc822 format available.

Message #239 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, martin rudalics <rudalics <at> gmx.at>, dj <at> redhat.com,
 fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 19 May 2021 09:46:21 +0300
Sorry, a bit offtopic: I noticed, the debbugs page for this report does not show
email anymore https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45200 the note at
the bottom says 

	This bug report was last modified 102 days ago.

Apparently the bugtracker broke. Any ideas, where should I report it?





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 09:48:01 GMT) Full text and rfc822 format available.

Message #242 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: bug-gnu-emacs <at> gnu.org, Konstantin Kharlamov <hi-angel <at> yandex.ru>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org, dj <at> redhat.com
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 19 May 2021 12:47:09 +0300
On May 19, 2021 9:46:21 AM GMT+03:00, Konstantin Kharlamov <hi-angel <at> yandex.ru> wrote:
> Sorry, a bit offtopic: I noticed, the debbugs page for this report
> does not show
> email anymore https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45200 the
> note at
> the bottom says 
> 
> 	This bug report was last modified 102 days ago.
> 
> Apparently the bugtracker broke. Any ideas, where should I report it?

There's nothing wrong with debbugs, it's your browser showing you a stale version of that page.  Trh reloading it while holding the Shift key or something.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 09:48:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 09:56:02 GMT) Full text and rfc822 format available.

Message #248 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <hi-angel <at> yandex.ru>
To: Eli Zaretskii <eliz <at> gnu.org>, bug-gnu-emacs <at> gnu.org, Stefan Monnier
 <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org, dj <at> redhat.com
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 19 May 2021 12:55:43 +0300
On Wed, 2021-05-19 at 12:47 +0300, Eli Zaretskii wrote:
> On May 19, 2021 9:46:21 AM GMT+03:00, Konstantin Kharlamov
> <hi-angel <at> yandex.ru> wrote:
> > Sorry, a bit offtopic: I noticed, the debbugs page for this report
> > does not show
> > email anymore https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45200 the
> > note at
> > the bottom says 
> > 
> >         This bug report was last modified 102 days ago.
> > 
> > Apparently the bugtracker broke. Any ideas, where should I report it?
> 
> There's nothing wrong with debbugs, it's your browser showing you a stale
> version of that page.  Trh reloading it while holding the Shift key or
> something.

Oh, now it works. 

For the record, I don't keep the tab opened (there's no reason for me), I always open it anew. So in a sense, the page is always "fresh". So I'm not sure what was the problem, but I confirm that now it works.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 09:56:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 10:10:01 GMT) Full text and rfc822 format available.

Message #254 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <hi-angel <at> yandex.ru>, bug-gnu-emacs <at> gnu.org,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: carlos <at> redhat.com, fweimer <at> redhat.com, 45200 <at> debbugs.gnu.org, dj <at> redhat.com
Subject: Re: bug#45200: [PATCH] Force Glibc to free the memory freed
Date: Wed, 19 May 2021 13:09:34 +0300
On May 19, 2021 12:55:43 PM GMT+03:00, Konstantin Kharlamov <hi-angel <at> yandex.ru> wrote:
> On Wed, 2021-05-19 at 12:47 +0300, Eli Zaretskii wrote:
> > On May 19, 2021 9:46:21 AM GMT+03:00, Konstantin Kharlamov
> > <hi-angel <at> yandex.ru> wrote:
> > > Sorry, a bit offtopic: I noticed, the debbugs page for this report
> > > does not show
> > > email anymore
> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45200 the
> > > note at
> > > the bottom says 
> > > 
> > >         This bug report was last modified 102 days ago.
> > > 
> > > Apparently the bugtracker broke. Any ideas, where should I report
> it?
> > 
> > There's nothing wrong with debbugs, it's your browser showing you a
> stale
> > version of that page.  Trh reloading it while holding the Shift key
> or
> > something.
> 
> Oh, now it works. 
> 
> For the record, I don't keep the tab opened (there's no reason for
> me), I always open it anew. So in a sense, the page is always "fresh".
> So I'm not sure what was the problem, but I confirm that now it works.

Browsers ard sneaky, they remember where you have been looking even if you close the tab.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Wed, 19 May 2021 10:10:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sat, 04 Dec 2021 23:21:01 GMT) Full text and rfc822 format available.

Message #260 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com,
 monnier <at> iro.umontreal.ca, Konstantin Kharlamov <Hi-Angel <at> yandex.ru>,
 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 05 Dec 2021 00:20:11 +0100
Eli Zaretskii <eliz <at> gnu.org> writes:

> Thanks, but is it really a good idea to call malloc_trim each time we
> free some chunk of memory?

Skimming this very long thread, I think the conclusion was that we
shouldn't do anything in Emacs on this point.  Does that sound correct?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Added tag(s) moreinfo. Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Sat, 04 Dec 2021 23:22:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 05 Dec 2021 06:25:01 GMT) Full text and rfc822 format available.

Message #265 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com,
 Konstantin Kharlamov <Hi-Angel <at> yandex.ru>, Eli Zaretskii <eliz <at> gnu.org>,
 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 05 Dec 2021 01:23:50 -0500
>> Thanks, but is it really a good idea to call malloc_trim each time we
>> free some chunk of memory?
> Skimming this very long thread, I think the conclusion was that we
> shouldn't do anything in Emacs on this point.  Does that sound correct?

For me the conclusion was that I'd be happy to see someone add a
`malloc-trim` primitive to ELisp, so that users can experiment with it,
e.g. by adding it to `post-gc-hook`.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 05 Dec 2021 07:08:01 GMT) Full text and rfc822 format available.

Message #268 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com,
 monnier <at> iro.umontreal.ca, Hi-Angel <at> yandex.ru, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 05 Dec 2021 09:07:29 +0200
> From: Lars Ingebrigtsen <larsi <at> gnus.org>
> Cc: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>,  carlos <at> redhat.com,
>   fweimer <at> redhat.com,  dj <at> redhat.com,  monnier <at> iro.umontreal.ca,
>   45200 <at> debbugs.gnu.org
> Date: Sun, 05 Dec 2021 00:20:11 +0100
> 
> Eli Zaretskii <eliz <at> gnu.org> writes:
> 
> > Thanks, but is it really a good idea to call malloc_trim each time we
> > free some chunk of memory?
> 
> Skimming this very long thread, I think the conclusion was that we
> shouldn't do anything in Emacs on this point.  Does that sound correct?

I don't really know whether there were any conclusions, and what they
were.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 05 Dec 2021 08:27:01 GMT) Full text and rfc822 format available.

Message #271 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com, Hi-Angel <at> yandex.ru,
 larsi <at> gnus.org, 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 05 Dec 2021 10:26:34 +0200
> From: Stefan Monnier <monnier <at> iro.umontreal.ca>
> Cc: Eli Zaretskii <eliz <at> gnu.org>,  Konstantin Kharlamov
>  <Hi-Angel <at> yandex.ru>,  carlos <at> redhat.com,  fweimer <at> redhat.com,
>   dj <at> redhat.com,  45200 <at> debbugs.gnu.org
> Date: Sun, 05 Dec 2021 01:23:50 -0500
> 
> >> Thanks, but is it really a good idea to call malloc_trim each time we
> >> free some chunk of memory?
> > Skimming this very long thread, I think the conclusion was that we
> > shouldn't do anything in Emacs on this point.  Does that sound correct?
> 
> For me the conclusion was that I'd be happy to see someone add a
> `malloc-trim` primitive to ELisp, so that users can experiment with it,
> e.g. by adding it to `post-gc-hook`.

That might be a good feature regardless, IMO.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 05 Dec 2021 20:00:02 GMT) Full text and rfc822 format available.

Message #274 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com,
 Konstantin Kharlamov <Hi-Angel <at> yandex.ru>, Eli Zaretskii <eliz <at> gnu.org>,
 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Memory leaks: (garbage-collect) fails to reclaim memory
Date: Sun, 05 Dec 2021 20:59:19 +0100
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

> For me the conclusion was that I'd be happy to see someone add a
> `malloc-trim` primitive to ELisp, so that users can experiment with it,
> e.g. by adding it to `post-gc-hook`.

Sure, sounds good to me.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Severity set to 'wishlist' from 'normal' Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Sun, 05 Dec 2021 20:00:03 GMT) Full text and rfc822 format available.

Changed bug title to 'Wishlist: There should be a `malloc-trim' function' from 'Memory leaks: (garbage-collect) fails to reclaim memory' Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Sun, 05 Dec 2021 20:01:02 GMT) Full text and rfc822 format available.

Removed tag(s) moreinfo. Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Fri, 21 Jan 2022 13:49:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#45200; Package emacs. (Sun, 01 May 2022 09:44:01 GMT) Full text and rfc822 format available.

Message #283 received at 45200 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: fweimer <at> redhat.com, dj <at> redhat.com, carlos <at> redhat.com,
 Stefan Monnier <monnier <at> iro.umontreal.ca>, Hi-Angel <at> yandex.ru,
 45200 <at> debbugs.gnu.org
Subject: Re: bug#45200: Wishlist: There should be a `malloc-trim' function
Date: Sun, 01 May 2022 11:43:40 +0200
Eli Zaretskii <eliz <at> gnu.org> writes:

>> For me the conclusion was that I'd be happy to see someone add a
>> `malloc-trim` primitive to ELisp, so that users can experiment with it,
>> e.g. by adding it to `post-gc-hook`.
>
> That might be a good feature regardless, IMO.

I've now added malloc-trim to Emacs 29.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




bug marked as fixed in version 29.1, send any further explanations to 45200 <at> debbugs.gnu.org and Konstantin Kharlamov <hi-angel <at> yandex.ru> Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Sun, 01 May 2022 09:44:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sun, 29 May 2022 11:24:03 GMT) Full text and rfc822 format available.

This bug report was last modified 1 year and 333 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.