From b77b54e068e8594c498fd6df291531e9685ebc00 Mon Sep 17 00:00:00 2001 From: rssdev10 Date: Thu, 19 May 2022 14:48:54 -0500 Subject: [PATCH] added new command line option heap_size_hint for greedy GC (#45369) * added new command line option heap_size_hint for greedy GC --- NEWS.md | 3 +++ base/options.jl | 1 + doc/man/julia.1 | 5 +++++ src/gc.c | 13 +++++++++++-- src/jloptions.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/jloptions.h | 1 + src/julia_internal.h | 3 +++ 7 files changed, 66 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index e4ef4fef7002c..9c2468e229861 100644 --- a/NEWS.md +++ b/NEWS.md @@ -32,6 +32,9 @@ Command-line option changes * `--math-mode=fast` is now a no-op ([#41638]). Users are encouraged to use the @fastmath macro instead, which has more well-defined semantics. * The `--threads` command-line option now accepts `auto|N[,auto|M]` where `M` specifies the number of interactive threads to create (`auto` currently means 1) ([#42302]). +* New option `--heap-size-hint=` gives a memory hint for triggering greedy garbage + collection. The size might be specified in bytes, kilobytes(1000k), megabytes(300M), + gigabytes(1.5G) Multi-threading changes ----------------------- diff --git a/base/options.jl b/base/options.jl index 63f73982b2e8e..48a8f7ff59d38 100644 --- a/base/options.jl +++ b/base/options.jl @@ -52,6 +52,7 @@ struct JLOptions rr_detach::Int8 strip_metadata::Int8 strip_ir::Int8 + heap_size_hint::UInt64 end # This runs early in the sysimage != is not defined yet diff --git a/doc/man/julia.1 b/doc/man/julia.1 index 9423cffd45cd4..b9914a24a3fd1 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -216,6 +216,11 @@ expressions. It first tries to use BugReporting.jl installed in current environm fallbacks to the latest compatible BugReporting.jl if not. For more information, see --bug-report=help. +.TP +--heap-size-hint= +Forces garbage collection if memory usage is higher that value. The memory hint might be +specified in megabytes (500M) or gigabytes (1.5G) + .TP --compile={yes*|no|all|min} Enable or disable JIT compiler, or request exhaustive or minimal compilation diff --git a/src/gc.c b/src/gc.c index e299661db87d4..8d917a5f52cc4 100644 --- a/src/gc.c +++ b/src/gc.c @@ -589,17 +589,19 @@ static int64_t last_gc_total_bytes = 0; // max_total_memory is a suggestion. We try very hard to stay // under this limit, but we will go above it rather than halting. #ifdef _P64 +typedef uint64_t memsize_t; #define default_collect_interval (5600*1024*sizeof(void*)) static size_t max_collect_interval = 1250000000UL; // Eventually we can expose this to the user/ci. -static uint64_t max_total_memory = (uint64_t) 2 * 1024 * 1024 * 1024 * 1024 * 1024; +memsize_t max_total_memory = (memsize_t) 2 * 1024 * 1024 * 1024 * 1024 * 1024; #else +typedef uint32_t memsize_t; #define default_collect_interval (3200*1024*sizeof(void*)) static size_t max_collect_interval = 500000000UL; // Work really hard to stay within 2GB // Alternative is to risk running out of address space // on 32 bit architectures. -static uint32_t max_total_memory = (uint32_t) 2 * 1024 * 1024 * 1024; +memsize_t max_total_memory = (memsize_t) 2 * 1024 * 1024 * 1024; #endif // global variables for GC stats @@ -3446,6 +3448,13 @@ void jl_gc_init(void) t_start = jl_hrtime(); } +void jl_gc_set_max_memory(uint64_t max_mem) { + if (max_mem > 0 + && max_mem < (uint64_t)1 << (sizeof(memsize_t) * 8 - 1)) { + max_total_memory = max_mem; + } +} + // callback for passing OOM errors from gmp JL_DLLEXPORT void jl_throw_out_of_memory_error(void) { diff --git a/src/jloptions.c b/src/jloptions.c index 8a8768b4d9b66..63d19063ebf45 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -85,6 +85,7 @@ JL_DLLEXPORT void jl_init_options(void) 0, // rr-detach 0, // strip-metadata 0, // strip-ir + 0, // heap-size-hint }; jl_options_initialized = 1; } @@ -177,6 +178,9 @@ static const char opts[] = " expressions. It first tries to use BugReporting.jl installed in current environment and\n" " fallbacks to the latest compatible BugReporting.jl if not. For more information, see\n" " --bug-report=help.\n\n" + + " --heap-size-hint= Forces garbage collection if memory usage is higher that value.\n" + " The memory hint might be specified in megabytes(500M) or gigabytes(1G)\n\n" ; static const char opts_hidden[] = @@ -242,6 +246,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) opt_rr_detach, opt_strip_metadata, opt_strip_ir, + opt_heap_size_hint, }; static const char* const shortopts = "+vhqH:e:E:L:J:C:it:p:O:g:"; static const struct option longopts[] = { @@ -297,6 +302,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) { "rr-detach", no_argument, 0, opt_rr_detach }, { "strip-metadata", no_argument, 0, opt_strip_metadata }, { "strip-ir", no_argument, 0, opt_strip_ir }, + { "heap-size-hint", required_argument, 0, opt_heap_size_hint }, { 0, 0, 0, 0 } }; @@ -755,6 +761,42 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) break; case opt_strip_ir: jl_options.strip_ir = 1; + break; + case opt_heap_size_hint: + if (optarg != NULL) { + size_t endof = strlen(optarg); + long double value = 0.0; + if (sscanf(optarg, "%Lf", &value) == 1 && value > 1e-7) { + char unit = optarg[endof - 1]; + uint64_t multiplier = 1ull; + switch (unit) { + case 'k': + case 'K': + multiplier <<= 10; + break; + case 'm': + case 'M': + multiplier <<= 20; + break; + case 'g': + case 'G': + multiplier <<= 30; + break; + case 't': + case 'T': + multiplier <<= 40; + break; + default: + break; + } + jl_options.heap_size_hint = (uint64_t)(value * multiplier); + + jl_gc_set_max_memory(jl_options.heap_size_hint); + } + } + if (jl_options.heap_size_hint == 0) + jl_errorf("julia: invalid argument to --heap-size-hint without memory size specified"); + break; default: jl_errorf("julia: unhandled option -- %c\n" diff --git a/src/jloptions.h b/src/jloptions.h index 9ac681c4ffacf..d7be95348f01f 100644 --- a/src/jloptions.h +++ b/src/jloptions.h @@ -56,6 +56,7 @@ typedef struct { int8_t rr_detach; int8_t strip_metadata; int8_t strip_ir; + uint64_t heap_size_hint; } jl_options_t; #endif diff --git a/src/julia_internal.h b/src/julia_internal.h index 74a16d718d7cd..b2115749685ef 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -467,6 +467,9 @@ void jl_gc_count_allocd(size_t sz) JL_NOTSAFEPOINT; void jl_gc_run_all_finalizers(jl_task_t *ct); void jl_release_task_stack(jl_ptls_t ptls, jl_task_t *task); +// Set GC memory trigger in bytes for greedy memory collecting +void jl_gc_set_max_memory(uint64_t max_mem); + JL_DLLEXPORT void jl_gc_queue_binding(jl_binding_t *bnd) JL_NOTSAFEPOINT; void gc_setmark_buf(jl_ptls_t ptls, void *buf, uint8_t, size_t) JL_NOTSAFEPOINT;