Note that the following original test is errorneous and has been superseded by the EDITED version below.
(progn
(message "Before: %S" (memory-use-counts))
(let ((x (make-list 100000000 0)))
(message "Use: %S" (memory-use-counts)))
(message "Garbage Collect: %S" (garbage-collect))
(message "After: %S" (memory-use-counts)))
The message output after running the progn
form is:
Before: (1974893 657 3944364 16613 2025974 923 92307)
Use: (101974903 658 3944364 16613 2026125 923 92310)
Garbage Collect: ((conses 16 100008801 10478) (symbols 48 2200 4) (strings 32 2545 1051) (string-bytes 1 82237) (vectors 16 3935) (vector-slots 8 69235 13732) (floats 8 11 12) (intervals 56 57 163) (buffers 992 7))
After: (101975693 659 3944734 16613 2029800 923 92506)
One clearly recognizes the huge list of 100000000 conses in the cons counter of the memory-use-counts.
Obviously the garbage-collect
after the let
-form does not free the memory for the conses of the huge list. Why?
emacs-version
:
GNU Emacs 27.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30) of 2019-08-16
and
GNU Emacs 26.2 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30) of 2019-04-12
EDIT:
User legoscia was so kind notify me about an error in my test with his answer.
Nevertheless, we can correct the test (with some self-check at the end) and the result of the new test still acknowledges that the memory for the huge list is not freed:
(progn
(message "Before: %S" (garbage-collect))
(let ((x (make-list 100000000 0)))
(message "Use: %S" (garbage-collect)))
(message "After: %S" (garbage-collect))
(message "Let's check again: %S" (garbage-collect)))
The output of this test is:
Before: ((conses 16 8012 7551) (symbols 48 2200 4) (strings 32 2533 939) (string-bytes 1 82159) (vectors 16 3912) (vector-slots 8 68701 11716) (floats 8 10 8) (intervals 56 26 21) (buffers 992 7))
Use: ((conses 16 100008064 733) (symbols 48 2200 4) (strings 32 2558 914) (string-bytes 1 83293) (vectors 16 3913) (vector-slots 8 68847 11570) (floats 8 10 8) (intervals 56 26 21) (buffers 992 7))
After: ((conses 16 100008106 691) (symbols 48 2200 4) (strings 32 2559 913) (string-bytes 1 83491) (vectors 16 3913) (vector-slots 8 68847 11570) (floats 8 10 8) (intervals 56 26 21) (buffers 992 7))
Let’s check again: ((conses 16 100008062 735) (symbols 48 2200 4) (strings 32 2559 913) (string-bytes 1 83495) (vectors 16 3913) (vector-slots 8 68847 11570) (floats 8 10 8) (intervals 56 26 21) (buffers 992 7))
The doc string of garbage-collect
says that the (nth 2 (assq 'conses (garbage-collect))))
is the number of conses found live in memory. So, this time the test should be valid.
Relevant part of the doc string of garbage-collect
:
Reclaim storage for Lisp objects no longer needed. Garbage collection happens automatically if you cons more than
gc-cons-threshold
bytes of Lisp data since previous garbage collection.garbage-collect
normally returns a list with info on amount of space in use, where each entry has the form (NAME SIZE USED FREE), where:
- NAME is a symbol describing the kind of objects this entry represents,
- SIZE is the number of bytes used by each one,
- USED is the number of those objects that were found live in the heap,
- FREE is the number of those objects that are not live but that Emacs
keeps around for future allocations (maybe because it does not know how
to return them to the OS).
message
calls (including the explicit gc) outside theprogn
?garbage-collect
calls afterwards -- and I just tested again. It seems like the memory usage is permanent. Though I didn't wait a long time to check the action of the timers of the garbage collector.