210 lines
6.6 KiB
OCaml
210 lines
6.6 KiB
OCaml
(*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*)
|
|
|
|
open Cmdliner
|
|
|
|
let ocaml_section = "OCAML RUNTIME OPTIONS"
|
|
|
|
let backtrace ~default =
|
|
let doc =
|
|
"Trigger the printing of a stack backtrace when an uncaught exception \
|
|
aborts the unikernel."
|
|
in
|
|
let doc = Arg.info ~docs:ocaml_section ~docv:"BOOL" ~doc [ "backtrace" ] in
|
|
Arg.(value & opt bool default doc)
|
|
|
|
let randomize_hashtables ~default =
|
|
let doc = "Turn on randomization of all hash tables by default." in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"BOOL" ~doc [ "randomize-hashtables" ]
|
|
in
|
|
Arg.(value & opt bool default doc)
|
|
|
|
let policy_of_int = function
|
|
| 0 -> `Next_fit
|
|
| 1 -> `First_fit
|
|
| 2 -> `Best_fit
|
|
| _ -> assert false
|
|
|
|
let int_of_policy = function `Next_fit -> 0 | `First_fit -> 1 | `Best_fit -> 2
|
|
|
|
let allocation_policy d =
|
|
let policy =
|
|
Arg.enum
|
|
[
|
|
("next-fit", `Next_fit);
|
|
("first-fit", `First_fit);
|
|
("best-fit", `Best_fit);
|
|
]
|
|
in
|
|
let doc =
|
|
"The policy used for allocating in the OCaml heap. Possible values are: \
|
|
$(i,next-fit), $(i,first-fit), $(i,best-fit). Best-fit is only supported \
|
|
since OCaml 4.10."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"ALLOCATION" ~doc [ "allocation-policy" ]
|
|
in
|
|
Arg.(value & opt policy (policy_of_int d.Gc.allocation_policy) doc)
|
|
|
|
let minor_heap_size d =
|
|
let doc = "The size of the minor heap (in words)." in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"WORDS" ~doc [ "minor-heap-size" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.minor_heap_size doc)
|
|
|
|
let major_heap_increment d =
|
|
let doc =
|
|
"The size increment for the major heap (in words). If less than or equal \
|
|
1000, it is a percentage of the current heap size. If more than 1000, it \
|
|
is a fixed number of words."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"PERCENT/WORDS" ~doc
|
|
[ "major-heap-increment" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.major_heap_increment doc)
|
|
|
|
let space_overhead d =
|
|
let doc =
|
|
"The percentage of live data of wasted memory, due to GC does not \
|
|
immediately collect unreachable blocks. The major GC speed is computed \
|
|
from this parameter, it will work more if smaller."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"PERCENT" ~doc [ "space-overhead" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.space_overhead doc)
|
|
|
|
let max_space_overhead d =
|
|
let doc =
|
|
"Heap compaction is triggered when the estimated amount of wasted memory \
|
|
exceeds this (percentage of live data). If above 1000000, compaction is \
|
|
never triggered."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"PERCENT" ~doc [ "max-space-overhead" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.max_overhead doc)
|
|
|
|
let gc_verbosity d =
|
|
let doc =
|
|
"GC messages on standard error output. Sum of flags. Check GC module \
|
|
documentation for details."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"VERBOSITY" ~doc [ "gc-verbosity" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.verbose doc)
|
|
|
|
let gc_window_size d =
|
|
let doc =
|
|
"The size of the window used by the major GC for smoothing out variations \
|
|
in its workload. Between 1 and 50."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"INT" ~doc [ "gc-window-size" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.window_size doc)
|
|
|
|
let custom_major_ratio d =
|
|
let doc =
|
|
"Target ratio of floating garbage to major heap size for out-of-heap \
|
|
memory held by custom values."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"RATIO" ~doc [ "custom-major-ratio" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.custom_minor_ratio doc)
|
|
|
|
let custom_minor_ratio d =
|
|
let doc =
|
|
"Bound on floating garbage for out-of-heap memory held by custom values in \
|
|
the minor heap."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"RATIO" ~doc [ "custom-minor-ratio" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.custom_minor_ratio doc)
|
|
|
|
let custom_minor_max_size d =
|
|
let doc =
|
|
"Maximum amount of out-of-heap memory for each custom value allocated in \
|
|
the minor heap."
|
|
in
|
|
let doc =
|
|
Arg.info ~docs:ocaml_section ~docv:"BYTES" ~doc [ "custom-minor-max-size" ]
|
|
in
|
|
Arg.(value & opt int d.Gc.custom_minor_max_size doc)
|
|
|
|
let stack_limit d =
|
|
let doc = "The maximum size of the fiber stacks (in words)." in
|
|
let doc = Arg.info ~docs:ocaml_section ~docv:"WORDS" ~doc [ "stack-limit" ] in
|
|
Arg.(value & opt int d.Gc.stack_limit doc)
|
|
|
|
let gc_control ~default =
|
|
let f minor_heap_size major_heap_increment space_overhead verbose max_overhead
|
|
stack_limit allocation_policy window_size custom_major_ratio
|
|
custom_minor_ratio custom_minor_max_size =
|
|
let allocation_policy = int_of_policy allocation_policy in
|
|
{
|
|
Gc.minor_heap_size;
|
|
major_heap_increment;
|
|
space_overhead;
|
|
verbose;
|
|
max_overhead;
|
|
stack_limit;
|
|
allocation_policy;
|
|
window_size;
|
|
custom_major_ratio;
|
|
custom_minor_ratio;
|
|
custom_minor_max_size;
|
|
}
|
|
in
|
|
Term.(
|
|
const f
|
|
$ minor_heap_size default
|
|
$ major_heap_increment default
|
|
$ space_overhead default
|
|
$ gc_verbosity default
|
|
$ max_space_overhead default
|
|
$ stack_limit default
|
|
$ allocation_policy default
|
|
$ gc_window_size default
|
|
$ custom_major_ratio default
|
|
$ custom_minor_ratio default
|
|
$ custom_minor_max_size default)
|
|
|
|
let setup ?backtrace:(b = Some false) ?randomize_hashtables:(r = Some false)
|
|
?gc_control:(c = Some (Gc.get ())) () =
|
|
let f backtrace randomize_hashtables gc_control =
|
|
let () =
|
|
match backtrace with None -> () | Some b -> Printexc.record_backtrace b
|
|
in
|
|
let () =
|
|
match randomize_hashtables with
|
|
| None | Some false -> ()
|
|
| Some true -> Hashtbl.randomize ()
|
|
in
|
|
let () = match gc_control with None -> () | Some c -> Gc.set c in
|
|
()
|
|
in
|
|
let some c = Term.(const Option.some $ c) in
|
|
let none = Term.const None in
|
|
let fold f d = Option.fold ~none ~some:(fun d -> some (f ~default:d)) d in
|
|
let b = fold backtrace b in
|
|
let r = fold randomize_hashtables r in
|
|
let c = fold gc_control c in
|
|
Term.(const f $ b $ r $ c)
|