diff --git a/doc/man/julia.1 b/doc/man/julia.1 index ee0f973c259fd..0c865e03f3042 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -227,8 +227,8 @@ fallbacks to the latest compatible BugReporting.jl if not. For more information, .TP --heap-size-hint= -Forces garbage collection if memory usage is higher than that value. The memory hint might be -specified in megabytes (500M) or gigabytes (1.5G) +Forces garbage collection if memory usage is higher than that value. The value can be +specified in units of K, M, G, T, or % of physical memory. .TP --compile={yes*|no|all|min} diff --git a/src/gc.c b/src/gc.c index 044dcf8113e9f..a920958307c48 100644 --- a/src/gc.c +++ b/src/gc.c @@ -4037,14 +4037,22 @@ void jl_gc_init(void) gc_num.max_pause = 0; gc_num.max_memory = 0; + uint64_t mem_reserve = 250*1024*1024; // LLVM + other libraries need some amount of memory + uint64_t min_heap_size_hint = mem_reserve + 1*1024*1024; + uint64_t hint = jl_options.heap_size_hint; #ifdef _P64 total_mem = uv_get_total_memory(); - uint64_t constrained_mem = uv_get_constrained_memory(); - if (constrained_mem > 0 && constrained_mem < total_mem) - jl_gc_set_max_memory(constrained_mem - 250*1024*1024); // LLVM + other libraries need some amount of memory + if (hint == 0) { + uint64_t constrained_mem = uv_get_constrained_memory(); + if (constrained_mem > 0 && constrained_mem < total_mem) + hint = constrained_mem; + } #endif - if (jl_options.heap_size_hint) - jl_gc_set_max_memory(jl_options.heap_size_hint - 250*1024*1024); + if (hint) { + if (hint < min_heap_size_hint) + hint = min_heap_size_hint; + jl_gc_set_max_memory(hint - mem_reserve); + } t_start = jl_hrtime(); } diff --git a/src/jloptions.c b/src/jloptions.c index 5d627687a38be..a5952637cd466 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -189,7 +189,7 @@ static const char opts[] = " --bug-report=help.\n\n" " --heap-size-hint= Forces garbage collection if memory usage is higher than that value.\n" - " The memory hint might be specified in megabytes(500M) or gigabytes(1G)\n\n" + " The value can be specified in units of K, M, G, T, or % of physical memory.\n\n" ; static const char opts_hidden[] = @@ -821,14 +821,24 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) case 'T': multiplier <<= 40; break; + case '%': + if (value > 100) + jl_errorf("julia: invalid percentage specified in --heap-size-hint"); + uint64_t mem = uv_get_total_memory(); + uint64_t cmem = uv_get_constrained_memory(); + if (cmem > 0 && cmem < mem) + mem = cmem; + multiplier = mem/100; + break; default: + jl_errorf("julia: invalid unit specified in --heap-size-hint"); break; } jl_options.heap_size_hint = (uint64_t)(value * multiplier); } } if (jl_options.heap_size_hint == 0) - jl_errorf("julia: invalid argument to --heap-size-hint without memory size specified"); + jl_errorf("julia: invalid memory size specified in --heap-size-hint"); break; case opt_gc_threads: diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 92bada23cb258..1d78df1e230da 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -1043,8 +1043,22 @@ end @test lines[3] == "foo" @test lines[4] == "bar" end -#heap-size-hint, we reserve 250 MB for non GC memory (llvm, etc.) -@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)" +end + +@testset "heap size hint" begin + #heap-size-hint, we reserve 250 MB for non GC memory (llvm, etc.) + @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)" + + mem = ccall(:uv_get_total_memory, UInt64, ()) + cmem = ccall(:uv_get_constrained_memory, UInt64, ()) + if cmem > 0 && cmem < mem + mem = cmem + end + maxmem = parse(Int, readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=25% -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`)) + hint = max(0.25mem, 251*1024*1024) + @test abs(maxmem - (hint - 250*1024*1024))/maxmem < 0.01 + + @test readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=10M -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`) == "$(1*1024*1024)" end ## `Main.main` entrypoint