Skip to content

Commit

Permalink
add ability to specify heap size hint as a percent (JuliaLang#52979)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JeffBezanson authored Feb 14, 2024
1 parent 8eaf83c commit 3e6ff3d
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 11 deletions.
4 changes: 2 additions & 2 deletions doc/man/julia.1
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ fallbacks to the latest compatible BugReporting.jl if not. For more information,

.TP
--heap-size-hint=<size>
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}
Expand Down
18 changes: 13 additions & 5 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
14 changes: 12 additions & 2 deletions src/jloptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ static const char opts[] =
" --bug-report=help.\n\n"

" --heap-size-hint=<size> 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[] =
Expand Down Expand Up @@ -823,14 +823,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:
Expand Down
22 changes: 20 additions & 2 deletions test/cmdlineargs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1043,8 +1043,26 @@ 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(UInt64, readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=25% -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`))
hint = max(mem÷4, 251*1024*1024) - 250*1024*1024
MAX32HEAP = 1536 * 1024 * 1024
if Int === Int32 && hint > MAX32HEAP
hint = MAX32HEAP
end
@test abs(Float64(maxmem) - hint)/maxmem < 0.05

@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
Expand Down

0 comments on commit 3e6ff3d

Please sign in to comment.