Why is available memory not being reused?

Asked by Derick Eddington on 2007-11-22

Running the below, and similar sequences, and watching the process's memory use, I see it continually increasing so that even after all the locations should no longer be reachable and there's a lot of memory mapped in, it will still map in more for another allocation. I'm wondering if this is unintended or not?

Ikarus Scheme version 0.0.1+ (revision 1106, build 2007-11-21)
Copyright (c) 2006-2007 Abdulaziz Ghuloum

> (define l1 (time (make-list 10000000 123))) (length l1)
running stats for (make-list 10000000 123):
    19 collections
    1716 ms elapsed cpu time, including 1592 ms collecting
    1791 ms elapsed real time, including 1672 ms collecting
    80012312 bytes allocated
> 10000000
> (set! l1 #f)
> (define l2 (time (make-list 10000000 -54321))) (length l2)
running stats for (make-list 10000000 -54321):
    19 collections
    1517 ms elapsed cpu time, including 1396 ms collecting
    1592 ms elapsed real time, including 1466 ms collecting
    80004120 bytes allocated
> 10000000
> (set! l2 #f)
> (define l3 (time (make-list 10000000 'blah))) (length l3)
running stats for (make-list 10000000 'blah):
    19 collections
    1576 ms elapsed cpu time, including 1452 ms collecting
    1822 ms elapsed real time, including 1699 ms collecting
    80000024 bytes allocated
> 10000000
> (set! l3 #f)
> (define l4 (time (make-list 10000000 #t))) (length l4)
running stats for (make-list 10000000 #t):
    19 collections
    1504 ms elapsed cpu time, including 1389 ms collecting
    1677 ms elapsed real time, including 1553 ms collecting
    80016408 bytes allocated
> 10000000
> (set! l4 #f)
> (collect)
;;; yet ikarus is still taking up +200MB ...

Question information

Language:
English Edit question
Status:
Solved
For:
Ikarus Scheme Edit question
Assignee:
No assignee Edit question
Solved by:
Abdulaziz Ghuloum
Solved:
2007-11-22
Last query:
2007-11-22
Last reply:
2007-11-22
Best Abdulaziz Ghuloum (aghuloum) said : #1

> (set! l4 #f)
> (collect)
;;; yet ikarus is still taking up +200MB ...

Right. If you call (collect) a few more times, memory usage should drop back to where it was at the beginning.

The reason for this is that collect does not collect the entire system on every run. Ikarus uses a multi-generation garbage collector in which different objects reside in different generations. Collection of younger objects occur more frequently than collection of older objects and objects do not get reclaimed until they're collected.

In your example, constructing a 10 million element list causes 19 garbage collections. So, you have a list made of pairs of different ages: the tail of the list might be in generation 3 (old) while the head of the list, which did not go through any collections, will still be in generation 0.

When you call (collect) at the end, this might sweep only generation-0's objects, reclaiming some of the dead objects. While it's true that the rest of the lists is inaccessible, the collector won't know that until it actually collects their generations. This will happen in later calls to (collect).

To demonstrate that the system won't go out of memory, try the following:
(let f () (set! t (time (make-list 10000000))) (set! t #f) (f))
Here, memory keeps on fluctuating up and down but Ikarus never runs out of memory.

Thanks Abdulaziz Ghuloum, that solved my question.