Skip to content

Commit 3e6ff3d

Browse files
authored
add ability to specify heap size hint as a percent (#52979)
also fix overflowed subtraction with size hints < 250mb --- we should pick some minimum soft heap limit; I chose 1mb here but it could be anything.
1 parent 8eaf83c commit 3e6ff3d

File tree

4 files changed

+47
-11
lines changed

4 files changed

+47
-11
lines changed

doc/man/julia.1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ fallbacks to the latest compatible BugReporting.jl if not. For more information,
229229

230230
.TP
231231
--heap-size-hint=<size>
232-
Forces garbage collection if memory usage is higher than that value. The memory hint might be
233-
specified in megabytes (500M) or gigabytes (1.5G)
232+
Forces garbage collection if memory usage is higher than that value. The value can be
233+
specified in units of K, M, G, T, or % of physical memory.
234234

235235
.TP
236236
--compile={yes*|no|all|min}

src/gc.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4037,14 +4037,22 @@ void jl_gc_init(void)
40374037
gc_num.max_pause = 0;
40384038
gc_num.max_memory = 0;
40394039

4040+
uint64_t mem_reserve = 250*1024*1024; // LLVM + other libraries need some amount of memory
4041+
uint64_t min_heap_size_hint = mem_reserve + 1*1024*1024;
4042+
uint64_t hint = jl_options.heap_size_hint;
40404043
#ifdef _P64
40414044
total_mem = uv_get_total_memory();
4042-
uint64_t constrained_mem = uv_get_constrained_memory();
4043-
if (constrained_mem > 0 && constrained_mem < total_mem)
4044-
jl_gc_set_max_memory(constrained_mem - 250*1024*1024); // LLVM + other libraries need some amount of memory
4045+
if (hint == 0) {
4046+
uint64_t constrained_mem = uv_get_constrained_memory();
4047+
if (constrained_mem > 0 && constrained_mem < total_mem)
4048+
hint = constrained_mem;
4049+
}
40454050
#endif
4046-
if (jl_options.heap_size_hint)
4047-
jl_gc_set_max_memory(jl_options.heap_size_hint - 250*1024*1024);
4051+
if (hint) {
4052+
if (hint < min_heap_size_hint)
4053+
hint = min_heap_size_hint;
4054+
jl_gc_set_max_memory(hint - mem_reserve);
4055+
}
40484056

40494057
t_start = jl_hrtime();
40504058
}

src/jloptions.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ static const char opts[] =
189189
" --bug-report=help.\n\n"
190190

191191
" --heap-size-hint=<size> Forces garbage collection if memory usage is higher than that value.\n"
192-
" The memory hint might be specified in megabytes(500M) or gigabytes(1G)\n\n"
192+
" The value can be specified in units of K, M, G, T, or % of physical memory.\n\n"
193193
;
194194

195195
static const char opts_hidden[] =
@@ -823,14 +823,24 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
823823
case 'T':
824824
multiplier <<= 40;
825825
break;
826+
case '%':
827+
if (value > 100)
828+
jl_errorf("julia: invalid percentage specified in --heap-size-hint");
829+
uint64_t mem = uv_get_total_memory();
830+
uint64_t cmem = uv_get_constrained_memory();
831+
if (cmem > 0 && cmem < mem)
832+
mem = cmem;
833+
multiplier = mem/100;
834+
break;
826835
default:
836+
jl_errorf("julia: invalid unit specified in --heap-size-hint");
827837
break;
828838
}
829839
jl_options.heap_size_hint = (uint64_t)(value * multiplier);
830840
}
831841
}
832842
if (jl_options.heap_size_hint == 0)
833-
jl_errorf("julia: invalid argument to --heap-size-hint without memory size specified");
843+
jl_errorf("julia: invalid memory size specified in --heap-size-hint");
834844

835845
break;
836846
case opt_gc_threads:

test/cmdlineargs.jl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,8 +1043,26 @@ end
10431043
@test lines[3] == "foo"
10441044
@test lines[4] == "bar"
10451045
end
1046-
#heap-size-hint, we reserve 250 MB for non GC memory (llvm, etc.)
1047-
@test readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=500M -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`) == "$((500-250)*1024*1024)"
1046+
end
1047+
1048+
@testset "heap size hint" begin
1049+
#heap-size-hint, we reserve 250 MB for non GC memory (llvm, etc.)
1050+
@test readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=500M -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`) == "$((500-250)*1024*1024)"
1051+
1052+
mem = ccall(:uv_get_total_memory, UInt64, ())
1053+
cmem = ccall(:uv_get_constrained_memory, UInt64, ())
1054+
if cmem > 0 && cmem < mem
1055+
mem = cmem
1056+
end
1057+
maxmem = parse(UInt64, readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=25% -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`))
1058+
hint = max(mem÷4, 251*1024*1024) - 250*1024*1024
1059+
MAX32HEAP = 1536 * 1024 * 1024
1060+
if Int === Int32 && hint > MAX32HEAP
1061+
hint = MAX32HEAP
1062+
end
1063+
@test abs(Float64(maxmem) - hint)/maxmem < 0.05
1064+
1065+
@test readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=10M -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`) == "$(1*1024*1024)"
10481066
end
10491067

10501068
## `Main.main` entrypoint

0 commit comments

Comments
 (0)