[Top][All Lists]

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

Re: Lisp-level macro to avoid excessive GC in memory-allocating code (wa

From: Ihor Radchenko
Subject: Re: Lisp-level macro to avoid excessive GC in memory-allocating code (was: Larger GC thresholds for non-interactive Emacs)
Date: Fri, 01 Jul 2022 19:12:05 +0800

Eli Zaretskii <eliz@gnu.org> writes:

>> > Please don't forget that GC doesn't only collects unused Lisp objects,
>> > it also does other useful memory-management related tasks.  It
>> > compacts buffer text and strings, and it frees unused slots in various
>> > caches (font cache, image cache, etc.).  You can find in the archives
>> > discussions where innocently-looking code could cause Emacs run out of
>> > memory because it used too many fonts without flushing the font cache
>> > (any program that works on the list of fonts returned by the likes of
>> > x-list-fonts is in danger of bumping into that).
>> Then, if we decide to implement the macro I am suggesting, such macro
>> should not affect memory allocation of such sensitive objects: font
>> cache, image cache, etc.
> Why not?  The same could happen with those cached objects.  And doing
> these jobs does take CPU time.

I do not have enough knowledge on the topic to argue on this. What I
wanted to say is that we can make some objects to be not affected by the
suggested macro if there are reasons to believe that it could be too

>> 1. In addition to directly bumping the TOTAL counter of newly allocated
>>    memory, we can introduce a new LOCAL counter holding recent
>>    allocations within current sexp.
>> 2. Every time we return from a sexp/self-quoting object into assignment,
>>    if we are inside the proposed macro and also assigning value to one
>>    of the pre-defined symbols, increase the upper LOCAL counter in the
>>    parent sexp. Otherwise, do not change the upper LOCAL counter.
>> 3. Perform GC according to TOTAL-LOCAL threshold value.
>> 4. When exiting the macro, set LOCAL to 0, unless inside another such
>>    macro.
> Is this aligned with what the implementation of the Lisp interpreter
> actually does?  I'm not sure we know, where we allocate memory for
> Lisp data, whether we are going to bind some variable to the produced
> data.  Thus "count recent allocations within the current sexp" sounds
> like non-trivial to implement.

I am not 100% sure, but AFAIK lisp interpreter always knows the current
lisp nesting level. The extra C-level variable I suggest may be an array
of max-lisp-eval-depth size. Then, at every given sexp nesting level, if
we know the current level, we automatically gain access to the
appropriate extra in-sexp memory allocation info.

It is also trivial to ensure that all the deeper nesting levels in the
array are set to 0 (after appropriate update of the value corresponding
to the current nesting)

> And what do you mean by "pre-defined symbols"? what makes a symbol
> "pre-defined"?

I was referring to

(with-no-gc '(pre-defined-symbol1 symbol2 ...) ...)

I am not sure if my description above is 100% accurate, but the general
idea is:
1. Introduce LOCAL variable holding total memory used to allocate
   objects within current lisp nesting. This variable can be represented
   by an array of max-lisp-eval-depth size.
2. GC is triggered based on TOTAL-LOCAL instead of currently used TOTAL.
3. LOCAL[i]+=LOCAL[i+1]; LOCAL[i+1]=0 should be done after anything
   potentially involving recursive sexp call, except symbol slot
   assignments to non-"pre-defined" symbols.
4. If we are assigning symbol value slot and the symbol value is not
   "pre-defined" in the macro, LOCAL is not incremented in 3, which will
   make all the memory allocated inside that sexp to be counted towards
   next GC threshold.

The above effectively allows GCs only upon returning from symbol
assignments (in let/setq/setf/etc). But I believe that it should not be
a big deal.

> I also am not sure we have the "parent sexp" in hand, but I'll let
> experts on the Lisp interpreter to comment on that.

Agree. I am nowhere expert. Mostly tried to look into setq
implementation I come up with something.

Hopefully people more familiar with the interpreter chime in.


reply via email to

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