Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added new command line option heap_size_hint for greedy GC #45369

Merged
merged 3 commits into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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=<size>` 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
-----------------------
Expand Down
1 change: 1 addition & 0 deletions base/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions doc/man/julia.1
Original file line number Diff line number Diff line change
Expand Up @@ -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=<size>
Forces garbage collection if memory usage is higher that value. The memory hint might be
specified in megabytes (500M) or gigabytes (1.5G)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these in multiples of 500x or 1.5x?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those are just examples. It arguably should be written specified in megabytes (e.g. 500M) or gigabytes (e.g. 1.5G)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these in multiples of 500x or 1.5x?

long double value is used for the numeric part. With 1e-7 restriction as a minimal value. So, even 0.000123G is working.


.TP
--compile={yes*|no|all|min}
Enable or disable JIT compiler, or request exhaustive or minimal compilation
Expand Down
13 changes: 11 additions & 2 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down
42 changes: 42 additions & 0 deletions src/jloptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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=<size> 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[] =
Expand Down Expand Up @@ -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[] = {
Expand Down Expand Up @@ -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 }
};

Expand Down Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions src/jloptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down