unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: "Gerd Möllmann" <gerd.moellmann@gmail.com>
To: Stefan Kangas <stefankangas@gmail.com>
Cc: Eli Zaretskii <eliz@gnu.org>,
	 pipcet@protonmail.com,  ofv@wanadoo.es, emacs-devel@gnu.org,
	 eller.helmut@gmail.com,  acorallo@gnu.org
Subject: Re: Some experience with the igc branch
Date: Fri, 27 Dec 2024 10:45:19 +0100	[thread overview]
Message-ID: <m2ikr5foi8.fsf@gmail.com> (raw)
In-Reply-To: <m2zfki6x5d.fsf@gmail.com> ("Gerd Möllmann"'s message of "Thu, 26 Dec 2024 20:51:10 +0100")

[-- Attachment #1: Type: text/plain, Size: 950 bytes --]

Gerd Möllmann <gerd.moellmann@gmail.com> writes:

> Stefan Kangas <stefankangas@gmail.com> writes:
>
>> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>>
>>> Coincidentally, I wrote this today, which might help, and would also be
>>> interesting to get some feedback for.
>>
>> This text looks good to me as a general introduction, especially if you
>> extend it to include these points also:
>
> Thanks.
>
>>> * Initialization
>>>  - Roots
>>>  - Threads
>>>  - Pools, Object formats
>>> * Lisp Object Allocation
>>> Object Header?
>>> * Malloc with roots
>>> * Memory barriers
>>
>> Do you intend to install this on the scratch/igc branch?
>
> Yes, when I'm a bit further. I think Eli wants a comment in igc.c like
> the one at xdisp.c starts with.

I've reached the point where I don't know what else to explain. Could
always be improved, of course, and so on. Please find attached, with
request for feedback.


[-- Attachment #2: Doc --]
[-- Type: text/x-org, Size: 11088 bytes --]

:PROPERTIES:
:ID:       0B687D90-0DE7-4BC3-B92E-1D582C175737
:END:
#+title: icg doc commebt
* Introduction / Garbage collection

Implementing a programming language like Lisp requires automatic
memory management which frees the memory of Lisp objects like conses,
strings etc. when they are no longer in use. The automatic memory
management used for Lisp is called garbage collection (GC), which is
performed by a garbage collector. Objects that are no longer used are
called garbage or dead, objects that are in use or called live
objects. The process of getting rid of garbage is called the GC.

A large number of GC algorithms and implementations exist which differ
in various dimensions. Emacs has two GC implementations which can be
chosen at compile-time. The traditional (old) GC, which was the only
one until recently, is a so-called mark-sweep, non-copying collector.
The new GC implementation in this file is an incremental,
generational, concurrent (igc) collector based on the MPS library from
Ravenbrook. It is a so-called copying collector. The terms used here
will become clearer in the following.

Emacs' traditional mark-sweep GC works in two phases:

1. The mark phase

   Start with a set of so-called (GC) roots that are known to contain
   live objects. Examples of roots in Emacs are

   - the bytecode stacks 
   - the specpdl (binding) stacks
   - Lisp variables defined in C with DEFVAR
   - the C stacks (aka control stacks)
   - ...

   Roots in a general sense are contiguous areas of memory, and they
   are either "exact" or "ambiguous".

   If we know that a root always contains only valid Lisp object
   references, the root is called exact. An Example for an exact root
   is the root for a DEFVAR. The DEFVAR variable always contains a
   valid reference to a Lisp object. The memory range of the root is
   the Lisp_Object C variable.

   If we only know that a root contains potential references to Lisp
   objects, the root is called ambiguous.  An example for an ambiguous
   root is the C stack.  The C stack can contain integers that look
   like a Lisp_Object or pointer to a Lisp object, but actually are
   just random integers.  Ambiguous roots are said to be scanned
   conservatively: we make the conservative assumption that we really
   found a reference, so that we don't discard objects that are only
   referenced from the C stack.

   The mark phase of the traditional GC scans all roots,
   conservatively or exactly, and marks the Lisp objects found
   referenced in the roots live, plus all Lisp objects reachable from
   them, recursively.  In the end, all live objects are marked, and all
   objects not marked are dead, i.e.  garbage.

2.  The sweep phase

   Sweeping means to free all objects that are not marked live.  The
   collector iterates over all allocated objects, live or dead, and
   frees the dead ones so that their memory can be reused.

The traditional mark-sweep GC implementation is

- Not concurrent.  Emacs calls GC explicitly in various places, and
  proceeds only when the GC is done.
- Not incremental.  The GC is not done in steps.
- Not generational.  The GC doesn't take advantage of the so-called
  generational hypothesis, which says that most objects used by a
  program die young, i.e.  are only used for a short period of time.
  Other GCs take this hypothesis into account to reduce pause times.
- Not copying.  Lisp objects are never copied by the GC.  They stay at
  the addresses where their initial allocation puts them.  Special
  facilities like allocation in blocks are implemented to avoid memory
  fragmentation.

In contrast, the new igc collector, using MPS, is

- Concurrent.  The GC runs in its own thread.  There are no explicit
  calls to start GC, and Emacs doesn't have to wait for the GC to
  complete.
- Incremental.  The GC is done in steps.
- Generational.  The GC takes advantage of the so-called
  generational hypothesis.
- Copying.  Lisp objects are copied by the GC, avoiding memory
  fragmentation.  Special care must be taken to take into account that
  the same Lisp object can have different addresses at different
  times.

The goal of igc is to reduce pause times when using Emacs
interactively.  The properties listed above which come from leveraging
MPS make that possible.

* MPS (Memory Pool System)

The MPS (Memory Pool System) is a C library developed by Ravenbrook
Inc. over several decades. It is used, for example, by the OpenDylan
project.

A guide and a reference manual for MPS can be found at
https://memory-pool-system.readthedocs.io. The following can only be a
rough and incomplete overview. It is recommended to read at least the
MPS Guide.

MPS uses "arenas" which consist of "pools". The pools represent memory
to allocate objects from that are subject to GC. Different types of
pools implement different GC strategies.

Pools have "object formats" that an application must supply when it
creates a pool. The most important part of an object format are a
handful of functions that an application must implement to perform
lowest-level operations on behalf of the MPS. These functions make it
possible to implement MPS without it having to know low-level details
about what application objects look like.

The most important MPS pool type is named AMC (Automatic Mostly
Copying). AMC implements a variant of a copying collector. Objects
allocated from AMS pools can therefore change their memory addresses.

When copying objects, a marker is left in the original object pointing
to its copy. This marker is also called a "tombstone". A "memory
barrier" is placed on the original object. Memory barrier means the
memory is read and/or write protected (e.g. with mprotect). The
barrier leads to MPS being invoked when an old object is accessed.
The whole process is called "object forwarding".

MPS makes sure that references to old objects are updated to refer to
their new addresses. Functions defined in the object format are used
by MPS to perform the lowest-level tasks of object forwarding, so that
MPS doesn't have to know application-specific details of how objects
look like. In the end, copying/forwarding is transparent to the
application.

AMC implements a "mostly-copying" collector, where "mostly" refers to
the fact that it supports ambiguous references. Ambiguous references
are those from ambiguous roots, where we can't tell if a reference is
real or not. If we would copy such an object, we wouldn't be able to
update their address in all references because we can't tell if the
ambiguous reference is real or just some random integer, and changing
it would have unforeseeable consequences. Ambiguously referenced
objects are therefore never copied, and their address does not change.

* The registry

The MPS shields itself from knowing application details, for example
which GC roots the application has, which threads, how objects look
like and so on. MPS has an internal model instead which describes
these details.

Emacs creates this model using the MPS API. For example, MPS cannot
know what Emacs' GC roots are. We tell MPS about Emacs' roots by
calling an MPS API function an MPS-internal model for the root, and
get back a handle that stands for the root. This handle later used to
refer to the model object. For example, if we want to delete a root
later, because we don't need it anymore, we call an MPS function
giving it the handle for the root we no longer need.

All other model objects are handled in the same way, threads, arenas,
pools, object formats and so on.

Igc collects all these MPS handles in a 'struct igc'. This "registry"
of MPS handles is found in the global variable 'global_igc' and thus
can be accessed from anywhere.

* Root scan functions

MPS allows us to specify roots having tailor-made scan functions that
Emacs implements. Scanning here refers to the process of finding
references in the memory area of the root, and telling MPS about the
references.

The function scan_specpdl is an example. We know the structure of a
bindings stack, so we can tell where references to Lisp objects can
be. This is generally better than letting MPS do the scanning itself,
because MPS can only scan the whole block word for word, ambiguously
or exactly.

All such scan functions in igc have the prefix scan_.

* Lisp object scan functions

Igc tells MPS how to scan Lisp objects allocated via MPS by specifying
a scan function for that purpose in an object format. This function is
'dflt_scan' in igc.c, which dispatches to various subroutines for
different Lisp object types.

The lower-level functions and macros igc defines in the call tree of
dflt_scan have names starting with 'fix'_ or 'FIX_', because they use
the MPS_FIX1 and MPS_FIX2 API to do their job. Please refer to the MPS
reference for details of MPS_FIX1/2.

* Initialization

Before we can use MPS, we must define and create various things that
MPS needs to know, i.e we create an MPS' internal model of Emacs. This
is done at application startup, and all objects are added to the
registry.

- Pools. We tell MPS which pools we want to use, and what the object
  formats are, i.e. which callbacks in Emacs MPS can use.
- Threads. We define which threads Emacs has, and add their C stacks
  as roots. This includes Emacs' main thread.
- Roots. We tell MPS about the various roots in Emacs, the DEFVARs,
  the byte code stack, staticpro, etc.
- ...

When we done all that, we tell MPS it can start doing its job.
  
* Lisp Object Allocation

All of Emacs' Lisp object allocation ultimately ends up done in igc's
'alloc_impl' function.

MPS allocation from pools is thread-specific, using so-called
"allocation points". These allocation points optimize allocation by
reducing thread-contention. Allocation points are associated with
pools, and there is one allocation point per thread.

The function 'thread_ap' in igc determines which allocation point to
use for the current thread and depending on the type of Lisp object
to allocate.

* Malloc with roots

In a number of places, Emacs allocates memory with its 'xmalloc'
function family and then stores references to Lisp objects there,
pointers or Lisp_Objects.

With the traditional GC, frequently, inadvertently collecting such
objects is prevented by inhibiting GC.

With igc, we do things differently. We don't want to temporarily stop
the GC thread to inhibit GC, as a design decision. Instead, we make
the malloc'd memory a root. The root is destroyed when the memory is
freed.

igc provides a number if functions for doing such allocations. For
example 'igc_xzalloc_ambig', 'igc_xpalloc_exact' and so on. Freeing
the memory must be done with 'igc_xfree'.

These functions are used throughout Emacs in äifdef HAVE_MPS. In
general, it's an erro to put references to Lisp objects in malloc'd
memory and not use the igc functions.

  reply	other threads:[~2024-12-27  9:45 UTC|newest]

Thread overview: 175+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-22 15:40 Some experience with the igc branch Óscar Fuentes
2024-12-22 17:18 ` Gerd Möllmann
2024-12-22 17:29 ` Gerd Möllmann
2024-12-22 17:41 ` Pip Cet via Emacs development discussions.
2024-12-22 17:56   ` Gerd Möllmann
2024-12-22 19:11   ` Óscar Fuentes
2024-12-23  0:05     ` Pip Cet via Emacs development discussions.
2024-12-23  1:00       ` Óscar Fuentes
2024-12-24 22:34         ` Pip Cet via Emacs development discussions.
2024-12-25  4:25           ` Freezing frame with igc Gerd Möllmann
2024-12-25 11:19             ` Pip Cet via Emacs development discussions.
2024-12-25 11:55             ` Óscar Fuentes
2024-12-23  3:42       ` Some experience with the igc branch Gerd Möllmann
2024-12-23  6:27     ` Jean Louis
2024-12-22 20:29   ` Helmut Eller
2024-12-22 20:50   ` Gerd Möllmann
2024-12-22 22:26     ` Pip Cet via Emacs development discussions.
2024-12-23  3:23       ` Gerd Möllmann
     [not found]         ` <m234ieddeu.fsf_-_@gmail.com>
     [not found]           ` <87ttaueqp9.fsf@protonmail.com>
     [not found]             ` <m2frme921u.fsf@gmail.com>
     [not found]               ` <87ldw6ejkv.fsf@protonmail.com>
     [not found]                 ` <m2bjx2h8dh.fsf@gmail.com>
2024-12-23 14:45                   ` Make Signal handling patch platform-dependent? Pip Cet via Emacs development discussions.
2024-12-23 14:54                     ` Gerd Möllmann
2024-12-23 15:11                       ` Eli Zaretskii
2024-12-23 13:35       ` Some experience with the igc branch Eli Zaretskii
2024-12-23 14:03         ` Discussion with MPS people Gerd Möllmann
2024-12-23 14:04           ` Gerd Möllmann
2024-12-23 15:07         ` Some experience with the igc branch Pip Cet via Emacs development discussions.
2024-12-23 15:26           ` Gerd Möllmann
2024-12-23 16:03             ` Pip Cet via Emacs development discussions.
2024-12-23 16:44               ` Eli Zaretskii
2024-12-23 17:16                 ` Pip Cet via Emacs development discussions.
2024-12-23 18:35                   ` Eli Zaretskii
2024-12-23 18:48                     ` Gerd Möllmann
2024-12-23 19:25                       ` Eli Zaretskii
2024-12-23 20:30                     ` Benjamin Riefenstahl
2024-12-23 23:39                       ` Pip Cet via Emacs development discussions.
2024-12-24 12:14                         ` Eli Zaretskii
2024-12-24 13:18                           ` Pip Cet via Emacs development discussions.
2024-12-24 13:42                           ` Benjamin Riefenstahl
2024-12-24  3:37                       ` Eli Zaretskii
2024-12-24  8:48                         ` Benjamin Riefenstahl
2024-12-24 13:52                           ` Eli Zaretskii
2024-12-24 13:54                             ` Benjamin Riefenstahl
2024-12-23 17:44               ` Gerd Möllmann
2024-12-23 19:00                 ` Eli Zaretskii
2024-12-23 19:37                   ` Eli Zaretskii
2024-12-23 20:49                   ` Gerd Möllmann
2024-12-23 21:43                     ` Helmut Eller
2024-12-23 21:49                       ` Pip Cet via Emacs development discussions.
2024-12-23 21:58                         ` Helmut Eller
2024-12-23 23:20                           ` Pip Cet via Emacs development discussions.
2024-12-24  5:38                             ` Helmut Eller
2024-12-24  6:27                               ` Gerd Möllmann
2024-12-24 10:09                               ` Pip Cet via Emacs development discussions.
2024-12-24  4:05                       ` Gerd Möllmann
2024-12-24  8:50                         ` Gerd Möllmann
2024-12-24  6:03                     ` SIGPROF + SIGCHLD and igc Gerd Möllmann
2024-12-24  8:23                       ` Helmut Eller
2024-12-24  8:39                         ` Gerd Möllmann
2024-12-25  9:22                           ` Helmut Eller
2024-12-25  9:43                             ` Gerd Möllmann
2024-12-24 13:05                         ` Eli Zaretskii
2024-12-25 10:46                           ` Helmut Eller
2024-12-25 12:45                             ` Eli Zaretskii
2024-12-24 12:54                       ` Eli Zaretskii
2024-12-24 12:59                         ` Gerd Möllmann
2024-12-27  8:08                       ` Helmut Eller
2024-12-27  8:51                         ` Eli Zaretskii
2024-12-27 14:53                           ` Helmut Eller
2024-12-27 15:09                             ` Pip Cet via Emacs development discussions.
2024-12-27 15:19                             ` Eli Zaretskii
2024-12-27  8:55                         ` Gerd Möllmann
2024-12-27 15:40                           ` Helmut Eller
2024-12-27 15:53                             ` Gerd Möllmann
2024-12-27 11:36                         ` Pip Cet via Emacs development discussions.
2024-12-27 16:14                           ` Helmut Eller
2024-12-28 10:02                             ` Helmut Eller
2024-12-23 23:37                   ` Some experience with the igc branch Pip Cet via Emacs development discussions.
2024-12-24  4:03                     ` Gerd Möllmann
2024-12-24 10:25                       ` Pip Cet via Emacs development discussions.
2024-12-24 10:50                         ` Gerd Möllmann
2024-12-24 13:15                         ` Eli Zaretskii
2024-12-24 12:26                       ` Eli Zaretskii
2024-12-24 12:56                         ` Gerd Möllmann
2024-12-24 13:19                           ` Pip Cet via Emacs development discussions.
2024-12-24 13:38                             ` Gerd Möllmann
2024-12-24 13:46                           ` Eli Zaretskii
2024-12-24 14:12                             ` Gerd Möllmann
2024-12-24 14:40                               ` Eli Zaretskii
2024-12-25  4:56                                 ` Gerd Möllmann
2024-12-25 12:19                                   ` Eli Zaretskii
2024-12-25 12:50                                     ` Gerd Möllmann
2024-12-25 13:00                                       ` Eli Zaretskii
2024-12-25 13:08                                         ` Gerd Möllmann
2024-12-25 13:26                                           ` Eli Zaretskii
2024-12-25 14:07                                             ` Gerd Möllmann
2024-12-25 14:43                                               ` Helmut Eller
2024-12-25 14:59                                                 ` Eli Zaretskii
2024-12-25 20:44                                                   ` Helmut Eller
2024-12-26  6:29                                                     ` Eli Zaretskii
2024-12-26  8:02                                                       ` Helmut Eller
2024-12-26  9:32                                                         ` Eli Zaretskii
2024-12-26 12:24                                                           ` Helmut Eller
2024-12-26 15:23                                                             ` Eli Zaretskii
2024-12-26 23:29                                                               ` Paul Eggert
2024-12-27  7:57                                                                 ` Eli Zaretskii
2024-12-27 19:34                                                                   ` Paul Eggert
2024-12-28  8:06                                                                     ` Eli Zaretskii
2024-12-25 15:02                                                 ` Gerd Möllmann
2024-12-25 13:09                                       ` Eli Zaretskii
2024-12-25 13:46                                         ` Gerd Möllmann
2024-12-25 14:37                                           ` Eli Zaretskii
2024-12-25 14:57                                             ` Gerd Möllmann
2024-12-25 15:28                                               ` Eli Zaretskii
2024-12-25 15:49                                                 ` Gerd Möllmann
2024-12-25 17:26                                                   ` Eli Zaretskii
2024-12-26  5:25                                                     ` Gerd Möllmann
2024-12-26  7:43                                                       ` Eli Zaretskii
2024-12-26  7:57                                                         ` Gerd Möllmann
2024-12-26 11:56                                                           ` Eli Zaretskii
2024-12-26 15:27                                                           ` Stefan Kangas
2024-12-26 19:51                                                             ` Gerd Möllmann
2024-12-27  9:45                                                               ` Gerd Möllmann [this message]
2024-12-27 13:56                                                                 ` Gerd Möllmann
2024-12-27 15:01                                                                   ` Pip Cet via Emacs development discussions.
2024-12-27 15:28                                                                     ` Eli Zaretskii
2024-12-27 15:47                                                                       ` Pip Cet via Emacs development discussions.
2024-12-27 16:18                                                                       ` Gerd Möllmann
2024-12-28  9:10                                                                         ` Stefan Kangas
2024-12-28  9:20                                                                           ` Gerd Möllmann
2024-12-28  9:24                                                                             ` Gerd Möllmann
2024-12-27 16:05                                                                     ` Gerd Möllmann
2024-12-27 17:00                                                                       ` Pip Cet via Emacs development discussions.
2024-12-27 16:37                                                                   ` Eli Zaretskii
2024-12-27 17:26                                                                     ` Pip Cet via Emacs development discussions.
2024-12-27 19:12                                                                       ` Gerd Möllmann
2024-12-28  7:36                                                                       ` Eli Zaretskii
2024-12-28  9:29                                                                       ` Eli Zaretskii
2024-12-27 18:21                                                                     ` Gerd Möllmann
2024-12-27 19:23                                                                       ` Pip Cet via Emacs development discussions.
2024-12-27 20:28                                                                         ` Gerd Möllmann
2024-12-28  6:08                                                                     ` Gerd Möllmann
2024-12-25 17:40                                       ` Pip Cet via Emacs development discussions.
2024-12-25 17:51                                         ` Eli Zaretskii
2024-12-26 15:24                                           ` Pip Cet via Emacs development discussions.
2024-12-26 15:57                                             ` Eli Zaretskii
2024-12-27 14:34                                               ` Pip Cet via Emacs development discussions.
2024-12-27 15:58                                                 ` Eli Zaretskii
2024-12-27 16:42                                                   ` Pip Cet via Emacs development discussions.
2024-12-26  5:27                                         ` Gerd Möllmann
2024-12-26  5:29                                         ` Gerd Möllmann
2024-12-24 21:18                               ` Pip Cet via Emacs development discussions.
2024-12-25  5:23                                 ` Gerd Möllmann
2024-12-25 10:48                                   ` Pip Cet via Emacs development discussions.
2024-12-25 13:40                                     ` Stefan Kangas
2024-12-25 17:03                                       ` Pip Cet via Emacs development discussions.
2024-12-26  5:22                                         ` Gerd Möllmann
2024-12-26  7:33                                           ` Eli Zaretskii
2024-12-26  8:02                                             ` Gerd Möllmann
2024-12-26 15:50                                             ` Stefan Kangas
2024-12-26 16:13                                               ` Eli Zaretskii
2024-12-26 19:40                                                 ` Gerd Möllmann
2024-12-26 17:01                                               ` Pip Cet via Emacs development discussions.
2024-12-26 19:45                                                 ` Gerd Möllmann
2024-12-26 20:05                                                   ` Eli Zaretskii
2024-12-26 20:12                                                     ` Gerd Möllmann
2024-12-26 16:12                                         ` Stefan Kangas
2024-12-26 17:05                                           ` Eli Zaretskii
2024-12-25 11:48                                   ` Helmut Eller
2024-12-25 11:58                                     ` Gerd Möllmann
2024-12-25 12:52                                     ` Eli Zaretskii
2024-12-25 12:31                                   ` Eli Zaretskii
2024-12-25 12:54                                     ` Gerd Möllmann
2024-12-24 12:11                     ` Eli Zaretskii
  -- strict thread matches above, loose matches on Subject: below --
2024-12-27  9:49 Sean Devlin
2024-12-27 12:34 ` Eli Zaretskii
2024-12-28  1:55   ` Sean Devlin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2ikr5foi8.fsf@gmail.com \
    --to=gerd.moellmann@gmail.com \
    --cc=acorallo@gnu.org \
    --cc=eliz@gnu.org \
    --cc=eller.helmut@gmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=ofv@wanadoo.es \
    --cc=pipcet@protonmail.com \
    --cc=stefankangas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).