From: Stefan Monnier <monnier@IRO.UMontreal.CA>
To: emacs-devel@gnu.org
Subject: Opportunistic garbage collection
Date: Wed, 24 Apr 2019 16:54:20 -0400 [thread overview]
Message-ID: <jwvwojj9lou.fsf-monnier+emacs@gnu.org> (raw)
I recently bumped into http://akrl.sdf.org/ where they mention a hack of
running the GC from an idle timer, and I was wondering why that would be
a good idea compared to the opportunistic GC we already do.
So I went a look for what we do, and the only thing I found was
/* If there is still no input available, ask for GC. */
if (!detect_input_pending_run_timers (0))
maybe_gc ();
in src/keyboard.c which doesn't seem to be of any use since this
maybe_gc will very rarely fire: the Elisp code we ran just before should
have called `maybe_gc` already (probably many times, actually).
So unless I missed the other place were we take advantage of idle time
to force an "early" GC, I suggest we install a patch like the one below
(which does more or less what I thought Emacs had been doing all along).
WDYT?
Stefan
diff --git a/lisp/startup.el b/lisp/startup.el
index a9b58c5e01..33fc901411 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -971,6 +971,13 @@ startup--load-user-init-file
(when debug-on-error-should-be-set
(setq debug-on-error debug-on-error-from-init-file))))
+(defcustom gc-cons-opportunistic-idle-time 5
+ "Number of seconds before trying an opportunistic GC.
+After this number of seconds of idle time, Emacs tries to collect
+garbage more eagerly (i.e. with thresholds halved) in the hope
+to avoid running the GC later during non-idle time."
+ :type 'integer)
+
(defun command-line ()
"A subroutine of `normal-top-level'.
Amongst another things, it parses the command-line arguments."
@@ -1368,6 +1375,16 @@ command-line
(eq face-ignored-fonts old-face-ignored-fonts))
(clear-face-cache)))
+ ;; Start opportunistic GC (after loading the init file, so we obey
+ ;; its settings). This is desirable for two reason:
+ ;; - It reduces the number of times we have to GC in the middle of
+ ;; an operation.
+ ;; - It means we GC when the C stack is short, reducing the risk of false
+ ;; positives from the conservative stack scanning.
+ (when gc-cons-opportunistic-idle-time
+ (run-with-idle-timer gc-cons-opportunistic-idle-time t
+ #'garbage-collect-maybe 2))
+
(setq after-init-time (current-time))
;; Display any accumulated warnings after all functions in
;; `after-init-hook' like `desktop-read' have finalized possible
diff --git a/src/alloc.c b/src/alloc.c
index 402fada1ad..14d387861c 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6016,6 +6016,28 @@ garbage_collect (void)
garbage_collect_1 (&gcst);
}
+DEFUN ("garbage-collect-maybe", Fgarbage_collect_maybe, Sgarbage_collect_maybe, 1, 1, "",
+ doc: /* Call `garbage-collect' if enough allocation happened.
+FACTOR determined what "enough" means here:
+a FACTOR of N means to run the GC if more than 1/Nth of the allocations
+needed to triger automatic allocation took place. */)
+ (Lisp_Object factor)
+{
+ CHECK_FIXNAT (factor);
+ EMACS_INT fact = XFIXNAT (factor);
+ byte_ct new_csgc = consing_since_gc * fact;
+ if (new_csgc / fact != consing_since_gc)
+ /* Overflow! */
+ garbage_collect ();
+ else
+ {
+ consing_since_gc = new_csgc;
+ maybe_gc ();
+ consing_since_gc /= fact;
+ }
+ return Qnil;
+}
+
DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
doc: /* Reclaim storage for Lisp objects no longer needed.
Garbage collection happens automatically if you cons more than
@@ -7416,6 +7438,7 @@ than 2**N, where N is this variable's value. N should be nonnegative. */);
defsubr (&Smake_finalizer);
defsubr (&Spurecopy);
defsubr (&Sgarbage_collect);
+ defsubr (&Sgarbage_collect_maybe);
defsubr (&Smemory_info);
defsubr (&Smemory_use_counts);
defsubr (&Ssuspicious_object);
diff --git a/src/keyboard.c b/src/keyboard.c
index dff8f6b2fc..237ced19ca 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2728,7 +2728,7 @@ read_char (int commandflag, Lisp_Object map,
/* If there is still no input available, ask for GC. */
if (!detect_input_pending_run_timers (0))
- maybe_gc ();
+ maybe_gc (); /* FIXME: Why? */
}
/* Notify the caller if an autosave hook, or a timer, sentinel or
next reply other threads:[~2019-04-24 20:54 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-24 20:54 Stefan Monnier [this message]
2019-04-25 0:17 ` Opportunistic garbage collection Paul Eggert
2019-04-25 6:27 ` Eli Zaretskii
2019-04-25 12:49 ` Stefan Monnier
2019-04-25 18:18 ` Stefan Monnier
2019-04-25 22:14 ` Paul Eggert
2019-04-26 0:15 ` Stefan Monnier
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=jwvwojj9lou.fsf-monnier+emacs@gnu.org \
--to=monnier@iro.umontreal.ca \
--cc=emacs-devel@gnu.org \
/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).