add PLT_INCREMENTAL_GC

Although calling `(collect-garbage 'incremental)` in a program with
a periodic task is the best way to request incremental collection, it's
handy for some experiments to have an environment variable that turns
it on permanently.

This change also makes incremental-mode minor collections log as "mIn"
instead of "min", and it changes the first field of the logged
`gc-info` structure to be a mode symbol instead of a boolean.
This commit is contained in:
Matthew Flatt 2015-11-27 07:51:44 -07:00
parent a0576e0378
commit ba8103bbde
14 changed files with 63 additions and 18 deletions

View File

@ -199,7 +199,11 @@ execution. Otherwise, @racket[#f] is returned.}
@section[#:tag "garbagecollection"]{Garbage Collection} @section[#:tag "garbagecollection"]{Garbage Collection}
Set the @as-index{@envvar{PLTDISABLEGC}} environment variable (to any Set the @as-index{@envvar{PLTDISABLEGC}} environment variable (to any
value) before Racket starts to disable @tech{garbage collection}. value) before Racket starts to disable @tech{garbage collection}. Set
the @as-index{@envvar{PLT_INCREMENTAL_GC}} environment variable to
request incremental mode at all times, but calling
@racket[(collect-garbage 'incremental)] in a program with a periodic
task is generally a better mechanism for requesting incremental mode.
In Racket 3m (the main variant of Racket), each garbage collection In Racket 3m (the main variant of Racket), each garbage collection
logs a message (see @secref["logging"]) at the @racket['debug] level with topic @racket['GC]. logs a message (see @secref["logging"]) at the @racket['debug] level with topic @racket['GC].
@ -209,18 +213,28 @@ versions of Racket may use a @racket[gc-info] @tech{prefab} structure
with additional fields: with additional fields:
@racketblock[ @racketblock[
(struct gc-info (major? pre-amount pre-admin-amount code-amount (struct gc-info (mode pre-amount pre-admin-amount code-amount
post-amount post-admin-amount post-amount post-admin-amount
start-process-time end-process-time start-process-time end-process-time
start-time end-time) start-time end-time)
#:prefab) #:prefab)
] ]
@itemlist[ @itemlist[
@item{The @racket[major?] field indicates whether the collection was @item{The @racket[mode] field is a symbol @racket['major],
a ``major'' collection that inspects all memory or a ``minor'' @racket['minor], or @racket['incremental]; @racket['major]
collection that mostly inspects just recent allocations.} indicates a collection that inspects all memory,
@racket['minor] indicates collection that mostly inspects just
recent allocations, and @racket['incremental] indicates a minor
collection that performs extra work toward the next major
collection.
@history[#:changed "6.3.0.7" @elem{Changed first field from a
boolean (@racket[#t] for
@racket['major], @racket[#f]
for @racket['minor]) to a
mode symbol.}]}
@item{The @racket[pre-amount] field reports place-local memory use @item{The @racket[pre-amount] field reports place-local memory use
(i.e., not counting the memory use of child places) in bytes at (i.e., not counting the memory use of child places) in bytes at
@ -286,6 +300,7 @@ collection mode, the text has the format
@elem{Processor time since startup of garbage collection's start})) @elem{Processor time since startup of garbage collection's start}))
]} ]}
@history[#:changed "6.3.0.7" @elem{Added @envvar{PLT_INCREMENTAL_GC}.}]
@defproc[(collect-garbage [request (or/c 'major 'minor 'incremental) 'major]) void?]{ @defproc[(collect-garbage [request (or/c 'major 'minor 'incremental) 'major]) void?]{
@ -314,7 +329,8 @@ garbage-collection mode, depending on @racket[request]:
major collections any sooner than they would occur otherwise.} major collections any sooner than they would occur otherwise.}
@item{@racket['incremental] --- Requests that each minor @item{@racket['incremental] --- Requests that each minor
collection performs incremental work toward a major collection. collection performs incremental work toward a major collection
(but does not request an immediate minor collection).
This incremental-mode request expires at the next major This incremental-mode request expires at the next major
collection. collection.

View File

@ -1542,6 +1542,9 @@ static int run_from_cmd_line(int argc, char *_argv[],
if (getenv("PLTDISABLEGC")) { if (getenv("PLTDISABLEGC")) {
scheme_enable_garbage_collection(0); scheme_enable_garbage_collection(0);
} }
if (getenv("PLT_INCREMENTAL_GC")) {
scheme_incremental_garbage_collection(1);
}
#endif #endif
scheme_set_logging_spec(syslog_level, stderr_level); scheme_set_logging_spec(syslog_level, stderr_level);

View File

@ -31,7 +31,7 @@ typedef int (*Fixup_Proc)(void *obj);
typedef int (*Fixup2_Proc)(void *obj, struct NewGC *); typedef int (*Fixup2_Proc)(void *obj, struct NewGC *);
typedef void (*GC_collect_start_callback_Proc)(void); typedef void (*GC_collect_start_callback_Proc)(void);
typedef void (*GC_collect_end_callback_Proc)(void); typedef void (*GC_collect_end_callback_Proc)(void);
typedef void (*GC_collect_inform_callback_Proc)(int master_gc, int major_gc, typedef void (*GC_collect_inform_callback_Proc)(int master_gc, int major_gc, int inc_gc,
intptr_t pre_used, intptr_t post_used, intptr_t pre_used, intptr_t post_used,
intptr_t pre_admin, intptr_t post_admin, intptr_t pre_admin, intptr_t post_admin,
intptr_t post_child_places_used); intptr_t post_child_places_used);
@ -174,6 +174,10 @@ GC2_EXTERN void GC_request_incremental_mode(void);
/* /*
Requests incremental mode; lasts until the next major collection. */ Requests incremental mode; lasts until the next major collection. */
GC2_EXTERN void GC_set_incremental_mode(int on);
/*
Sets whether incremental mode is the default. */
GC2_EXTERN void GC_free_all(void); GC2_EXTERN void GC_free_all(void);
/* /*
Releases all memory, removes all signal handlers, etc. Releases all memory, removes all signal handlers, etc.

View File

@ -252,7 +252,7 @@ MAYBE_UNUSED static void GCVERBOSEprintf(NewGC *gc, const char *fmt, ...) {
#define AGE_GEN_0_TO_GEN_HALF(gc) ((gc)->memory_in_use > (GEN0_MAX_SIZE * 8)) #define AGE_GEN_0_TO_GEN_HALF(gc) ((gc)->memory_in_use > (GEN0_MAX_SIZE * 8))
/* Incremental mode */ /* Incremental mode */
#define ALWAYS_COLLECT_INCREMENTAL_ON_MINOR 0 static int always_collect_incremental_on_minor = 0;
#define INCREMENTAL_COLLECT_FUEL_PER_100M (24 * 1024) #define INCREMENTAL_COLLECT_FUEL_PER_100M (24 * 1024)
#define INCREMENTAL_REPAIR_FUEL_PER_100M 512 #define INCREMENTAL_REPAIR_FUEL_PER_100M 512
@ -3558,6 +3558,11 @@ void GC_request_incremental_mode(void)
gc->incremental_requested = 1; gc->incremental_requested = 1;
} }
void GC_set_incremental_mode(int on)
{
always_collect_incremental_on_minor = 1;
}
void GC_enable_collection(int on) void GC_enable_collection(int on)
{ {
NewGC *gc = GC_get_GC(); NewGC *gc = GC_get_GC();
@ -5847,7 +5852,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin
gc->need_fixup = 0; gc->need_fixup = 0;
do_incremental = (!gc->gc_full && (gc->incremental_requested do_incremental = (!gc->gc_full && (gc->incremental_requested
|| ALWAYS_COLLECT_INCREMENTAL_ON_MINOR)); || always_collect_incremental_on_minor));
if (!postmaster_and_place_gc(gc)) if (!postmaster_and_place_gc(gc))
do_incremental = 0; do_incremental = 0;
@ -6053,7 +6058,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin
is_master = (gc == MASTERGC); is_master = (gc == MASTERGC);
#endif #endif
park_for_inform_callback(gc); park_for_inform_callback(gc);
gc->GC_collect_inform_callback(is_master, gc->gc_full, gc->GC_collect_inform_callback(is_master, gc->gc_full, do_incremental,
old_mem_use + old_gen0, gc->memory_in_use, old_mem_use + old_gen0, gc->memory_in_use,
old_mem_allocated, mmu_memory_allocated(gc->mmu)+gc->phantom_count, old_mem_allocated, mmu_memory_allocated(gc->mmu)+gc->phantom_count,
gc->child_gc_total); gc->child_gc_total);
@ -6135,7 +6140,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin
if (sub_lmi.ran) { if (sub_lmi.ran) {
if (gc->GC_collect_inform_callback) { if (gc->GC_collect_inform_callback) {
park_for_inform_callback(gc); park_for_inform_callback(gc);
gc->GC_collect_inform_callback(1, sub_lmi.full, gc->GC_collect_inform_callback(1, sub_lmi.full, 0,
sub_lmi.pre_used, sub_lmi.post_used, sub_lmi.pre_used, sub_lmi.post_used,
sub_lmi.pre_admin, sub_lmi.post_admin, sub_lmi.pre_admin, sub_lmi.post_admin,
0); 0);

View File

@ -226,6 +226,7 @@ EXPORTS
scheme_collect_garbage scheme_collect_garbage
scheme_collect_garbage_minor scheme_collect_garbage_minor
scheme_enable_garbage_collection scheme_enable_garbage_collection
scheme_incremental_garbage_collection
scheme_malloc_immobile_box scheme_malloc_immobile_box
scheme_free_immobile_box scheme_free_immobile_box
scheme_add_gc_callback scheme_add_gc_callback

View File

@ -234,6 +234,7 @@ EXPORTS
scheme_collect_garbage scheme_collect_garbage
scheme_collect_garbage_minor scheme_collect_garbage_minor
scheme_enable_garbage_collection scheme_enable_garbage_collection
scheme_incremental_garbage_collection
GC_variable_stack GC_variable_stack
GC_register_traversers GC_register_traversers
GC_resolve GC_resolve

View File

@ -237,6 +237,7 @@ scheme_gc_ptr_ok
scheme_collect_garbage scheme_collect_garbage
scheme_collect_garbage_minor scheme_collect_garbage_minor
scheme_enable_garbage_collection scheme_enable_garbage_collection
scheme_incremental_garbage_collection
GC_register_traversers GC_register_traversers
GC_resolve GC_resolve
GC_mark GC_mark

View File

@ -241,6 +241,7 @@ scheme_gc_ptr_ok
scheme_collect_garbage scheme_collect_garbage
scheme_collect_garbage_minor scheme_collect_garbage_minor
scheme_enable_garbage_collection scheme_enable_garbage_collection
scheme_incremental_garbage_collection
GC_variable_stack GC_variable_stack
GC_register_traversers GC_register_traversers
GC_resolve GC_resolve

View File

@ -1658,6 +1658,13 @@ void scheme_enable_garbage_collection(int on)
#endif #endif
} }
void scheme_incremental_garbage_collection(int on)
{
#ifdef MZ_PRECISE_GC
GC_set_incremental_mode(on);
#endif
}
MZ_DO_NOT_INLINE(uintptr_t scheme_get_deeper_address(void)); MZ_DO_NOT_INLINE(uintptr_t scheme_get_deeper_address(void));
uintptr_t scheme_get_deeper_address(void) uintptr_t scheme_get_deeper_address(void)

View File

@ -464,6 +464,7 @@ MZ_EXTERN void scheme_gc_ptr_ok(void *p);
MZ_EXTERN void scheme_collect_garbage(void); MZ_EXTERN void scheme_collect_garbage(void);
MZ_EXTERN void scheme_collect_garbage_minor(void); MZ_EXTERN void scheme_collect_garbage_minor(void);
MZ_EXTERN void scheme_enable_garbage_collection(int on); MZ_EXTERN void scheme_enable_garbage_collection(int on);
MZ_EXTERN void scheme_incremental_garbage_collection(int on);
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
# ifndef USE_THREAD_LOCAL # ifndef USE_THREAD_LOCAL

View File

@ -363,6 +363,7 @@ void (*scheme_gc_ptr_ok)(void *p);
void (*scheme_collect_garbage)(void); void (*scheme_collect_garbage)(void);
void (*scheme_collect_garbage_minor)(void); void (*scheme_collect_garbage_minor)(void);
void (*scheme_enable_garbage_collection)(int on); void (*scheme_enable_garbage_collection)(int on);
void (*scheme_incremental_garbage_collection)(int on);
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
# ifndef USE_THREAD_LOCAL # ifndef USE_THREAD_LOCAL
void **GC_variable_stack; void **GC_variable_stack;

View File

@ -263,6 +263,7 @@
scheme_extension_table->scheme_collect_garbage = scheme_collect_garbage; scheme_extension_table->scheme_collect_garbage = scheme_collect_garbage;
scheme_extension_table->scheme_collect_garbage_minor = scheme_collect_garbage_minor; scheme_extension_table->scheme_collect_garbage_minor = scheme_collect_garbage_minor;
scheme_extension_table->scheme_enable_garbage_collection = scheme_enable_garbage_collection; scheme_extension_table->scheme_enable_garbage_collection = scheme_enable_garbage_collection;
scheme_extension_table->scheme_incremental_garbage_collection = scheme_incremental_garbage_collection;
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
# ifndef USE_THREAD_LOCAL # ifndef USE_THREAD_LOCAL
scheme_extension_table->GC_variable_stack = GC_variable_stack; scheme_extension_table->GC_variable_stack = GC_variable_stack;

View File

@ -263,6 +263,7 @@
#define scheme_collect_garbage (scheme_extension_table->scheme_collect_garbage) #define scheme_collect_garbage (scheme_extension_table->scheme_collect_garbage)
#define scheme_collect_garbage_minor (scheme_extension_table->scheme_collect_garbage_minor) #define scheme_collect_garbage_minor (scheme_extension_table->scheme_collect_garbage_minor)
#define scheme_enable_garbage_collection (scheme_extension_table->scheme_enable_garbage_collection) #define scheme_enable_garbage_collection (scheme_extension_table->scheme_enable_garbage_collection)
#define scheme_incremental_garbage_collection (scheme_extension_table->scheme_incremental_garbage_collection)
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
# ifndef USE_THREAD_LOCAL # ifndef USE_THREAD_LOCAL
#define GC_variable_stack (scheme_extension_table->GC_variable_stack) #define GC_variable_stack (scheme_extension_table->GC_variable_stack)

View File

@ -223,7 +223,7 @@ THREAD_LOCAL_DECL(static double end_this_gc_real_time);
static void get_ready_for_GC(void); static void get_ready_for_GC(void);
static void done_with_GC(void); static void done_with_GC(void);
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
static void inform_GC(int master_gc, int major_gc, intptr_t pre_used, intptr_t post_used, static void inform_GC(int master_gc, int major_gc, int inc_gc, intptr_t pre_used, intptr_t post_used,
intptr_t pre_admin, intptr_t post_admin, intptr_t post_child_places_used); intptr_t pre_admin, intptr_t post_admin, intptr_t post_child_places_used);
#endif #endif
@ -9252,7 +9252,7 @@ static char *gc_num(char *nums, intptr_t v)
END_XFORM_SKIP; END_XFORM_SKIP;
#endif #endif
static void inform_GC(int master_gc, int major_gc, static void inform_GC(int master_gc, int major_gc, int inc_gc,
intptr_t pre_used, intptr_t post_used, intptr_t pre_used, intptr_t post_used,
intptr_t pre_admin, intptr_t post_admin, intptr_t pre_admin, intptr_t post_admin,
intptr_t post_child_places_used) intptr_t post_child_places_used)
@ -9282,7 +9282,9 @@ static void inform_GC(int master_gc, int major_gc,
vec = scheme_false; vec = scheme_false;
if (!master_gc && gc_info_prefab) { if (!master_gc && gc_info_prefab) {
vec = scheme_make_vector(11, scheme_false); vec = scheme_make_vector(11, scheme_false);
SCHEME_VEC_ELS(vec)[1] = (major_gc ? scheme_true : scheme_false); SCHEME_VEC_ELS(vec)[1] = (major_gc
? major_symbol
: (inc_gc ? incremental_symbol : minor_symbol));
SCHEME_VEC_ELS(vec)[2] = scheme_make_integer(pre_used); SCHEME_VEC_ELS(vec)[2] = scheme_make_integer(pre_used);
SCHEME_VEC_ELS(vec)[3] = scheme_make_integer(pre_admin); SCHEME_VEC_ELS(vec)[3] = scheme_make_integer(pre_admin);
SCHEME_VEC_ELS(vec)[4] = scheme_make_integer(scheme_code_page_total); SCHEME_VEC_ELS(vec)[4] = scheme_make_integer(scheme_code_page_total);
@ -9311,7 +9313,7 @@ static void inform_GC(int master_gc, int major_gc,
#ifdef MZ_USE_PLACES #ifdef MZ_USE_PLACES
scheme_current_place_id, scheme_current_place_id,
#endif #endif
(master_gc ? "MST" : (major_gc ? "MAJ" : "min")), (master_gc ? "MST" : (major_gc ? "MAJ" : (inc_gc ? "mIn" : "min"))),
gc_num(nums, pre_used), gc_num(nums, pre_admin - pre_used), gc_num(nums, pre_used), gc_num(nums, pre_admin - pre_used),
gc_num(nums, scheme_code_page_total), gc_num(nums, scheme_code_page_total),
gc_num(nums, delta), ((admin_delta < 0) ? "" : "+"), gc_num(nums, admin_delta), gc_num(nums, delta), ((admin_delta < 0) ? "" : "+"), gc_num(nums, admin_delta),