Subject: bug#79023: 30.1.90; Suspicion of memory leak on internal_redisplay (MacOS)

From: Eli Zaretskii <[email-masked]>
Date: Wed, 16 Jul 2025 16:24:41 +0300

> From: Przemysław Alexander Kamiński
>  <[email-masked]>
> Cc: [email-masked]
> Date: Wed, 16 Jul 2025 14:35:51 +0200
> 
> > I also am not sure these are real leaks.  Emacs Lisp programs trigger
> > memory allocation when they create Lisp objects, but they don't
> > themselves free memory they allocated this way when the objects are no
> > longer needed.  Instead, the process known as "garbage collection"
> > (GC) is initiated by Emacs from time to time, and "collects garbage"
> > by finding Lisp objects no longer referenced by any other object, and
> > freeing their memory.  (Apologies for the lecture if you already know
> > all that.)  Thus, programs that expect memory to be released
> > immediately when the object goes out of scope will think Emacs is a
> > very leaky application, because that's not how Emacs Lisp works.
> >
> > Are you sure the information you collected is not of this kind?
> 
> I'm quite confident it's not the case. Garbage collector doesn't clean it up.

How do you see that GC doesn't clean up?

> Here's my line of thinking:
> - 1Gb of Emacs after launch and list-packages is huge (even with hefty config)

Sorry, I don't understand what that means.  Are you saying that you
load many packages at startup?  How many?

Could we please start the measurements from "emacs -Q", to avoid
potential influence of too many unknowns?

I've just left "emacs -Q" running for 10 minutes, after setting
blink-cursor-blinks to zero (so it keeps blinking indefinitely), and
not only did it not grow in memory, it _freed_ some memory.

> - This wouldn't go unnoticed, so most likely isn't the problem of the core code...
> - I searched before and found also other entries on web which point to Emacs performance on MacOS
> - Also I have Emacs config synced to my gaming Windows machine and I didn't experience any slowness (it was blazingly fast actually)
> - All profiling I've done so far look good
> - Which means something must be happening on MacOS integration

It's possible that on macOS there's some leak, but we need a much more
specific information to find where it happens.  Just looking at the
memory allocation calls will never tell us anything useful, because
Emacs calls malloc _a_lot_.

> The facts for me are:
> - Emacs is bloating over time and freezes at some point for unknown reasons
> - Over the time Emacs is more and more slugish, M-x taking 0.7s to think etc.
> - After multiple scrupoulous review of config, timers background processess etc.

I'm not arguing against the facts.

> I've noticed that on built Emacs there's allocation for every single blink of cursor on screen. Isn't this weird even if that wouldn't leak.

No, it isn't weird at all.  Cursor-blinking in Emacs is not a terminal
function, it is Emacs actively turning the cursor off and on again,
every 0.5 sec.  To do that, it runs a 2 Hz timer, which expires every
0.5 sec, then turns the cursor on or off, and then computes the time
it should expire next.  All these actions allocate memory (which is
then freed, some of it immediately and some later, via GC).

> I've done more testing today with different build flags and some guesses that I have:
> - Some allocated strings aren't marked as autorelease, so they stay

What do you mean by "marked autorelease"?  Lisp strings are released
by GC when they are no longer referenced from any other object.
There's no such thing as "autorelease strings" in Emacs.

> - For some reason system doesn't know that this allocated space is no longer used and doesn't GC it

How do you see that?  And which space is it, allocated by what
functions?

> - Slowness is caused by immense fragmentation of memory caused by small allocations far away from each other

Emacs relies on the system malloc to be able to avoid fragmentation.
Where that is not guaranteed (such as on MS-Windows), Emacs has its
own replacements for the system malloc, which avoid fragmentation.

> - During deallocation hashes aren't deallocated completely

Which hashes are those?

> - There's missing some MacOS specific call that should be made in order for it to optimize

Which calls, and where are they missing?

> - NSEvents are being stopped in flight without deallocation and they keep references to the memory

This should be addressed by some macOS expert.  Alan, can you help
here?