diff options
author | Gabriel Scherer <gabriel.scherer@gmail.com> | 2020-01-21 21:42:03 +0100 |
---|---|---|
committer | Gabriel Scherer <gabriel.scherer@gmail.com> | 2020-04-01 16:37:28 +0200 |
commit | ff6b20098f7f51758d78546af4bb8747cdc8c9f4 (patch) | |
tree | bcfe6ca8ad604356d327a9efd4df9564c6fe77f7 /stdlib | |
parent | e10e2bfa992c977572ce9dda82ba22b449f54e81 (diff) | |
download | ocaml-ff6b20098f7f51758d78546af4bb8747cdc8c9f4.tar.gz |
Gc.Memprof.start: take a record instead of 5 optional parameters
The Gc.Memprof module provides a low-level API, that will hopefully be
paired with user libraries that provide high-level instrumentation
choices.
A natural question is: how are the higher-level API going to expose
their choice of instrumentation to their users? With the current
Memprof.start API (before this patch), they would have to either
provide their own `start` function wrapping Memprof.start, or provide
a tuple of callbacks for to their users to pass to Memprof.start
themselves.
val start : params -> unit
(* or *)
val callback : params ->
((allocation -> foo option) * (allocation -> bar option) * ... )
With an explicit record, it is easier for libraries to expose an
instrumentation choice (possibility parametrized over
user-provided settings):
val tracker : params -> (foo, bar) Gc.Memprof.tracker
In addition, providing a record instead of optional parameters makes
it much easier to provide "default settings" (helper functions) that
instantiates the types `'minor` and `'ḿajor`, see for example
`simple_tracker` in this patch (which stores the same information for
the minor and major heap, and does not observe promotion), or to later
define checking predicates that can verify that a given choice of
callbacks is sensible (for example: providing a major-dealloc callback
but no promotion callback (dropping all tracked value on promotion) is
probably not a good idea).
Bootstrap: to avoid requiring an awkward bootstrap, this commit keeps
the (now unused) function caml_memprof_start_byt unchanged -- it is
used in the bootstrap binaries, so removing it would break the
build. The intention is to remove it in the following commit.
Diffstat (limited to 'stdlib')
-rw-r--r-- | stdlib/gc.ml | 36 | ||||
-rw-r--r-- | stdlib/gc.mli | 39 |
2 files changed, 46 insertions, 29 deletions
diff --git a/stdlib/gc.ml b/stdlib/gc.ml index 771dea51b8..52433ca432 100644 --- a/stdlib/gc.ml +++ b/stdlib/gc.ml @@ -127,27 +127,31 @@ module Memprof = unmarshalled : bool; callstack : Printexc.raw_backtrace } + type ('minor, 'major) tracker = { + alloc_minor: allocation -> 'minor option; + alloc_major: allocation -> 'major option; + promote: 'minor -> 'major option; + dealloc_minor: 'minor -> unit; + dealloc_major: 'major -> unit; + } + + let null_tracker = { + alloc_minor = (fun _ -> None); + alloc_major = (fun _ -> None); + promote = (fun _ -> None); + dealloc_minor = (fun _ -> ()); + dealloc_major = (fun _ -> ()); + } + external c_start : - float -> int -> - (allocation -> 'minor option) -> - (allocation -> 'major option) -> - ('minor -> 'major option) -> - ('minor -> unit) -> - ('major -> unit) -> - unit - = "caml_memprof_start_byt" "caml_memprof_start" + float -> int -> ('minor, 'major) tracker -> unit + = "caml_memprof_start" let start ~sampling_rate ?(callstack_size = max_int) - ?(minor_alloc_callback = fun _ -> None) - ?(major_alloc_callback = fun _ -> None) - ?(promote_callback = fun _ -> None) - ?(minor_dealloc_callback = fun _ -> ()) - ?(major_dealloc_callback = fun _ -> ()) () = - c_start sampling_rate callstack_size minor_alloc_callback - major_alloc_callback promote_callback minor_dealloc_callback - major_dealloc_callback + tracker = + c_start sampling_rate callstack_size tracker external stop : unit -> unit = "caml_memprof_stop" end diff --git a/stdlib/gc.mli b/stdlib/gc.mli index fb84421bd9..77682456f7 100644 --- a/stdlib/gc.mli +++ b/stdlib/gc.mli @@ -458,15 +458,32 @@ module Memprof : type of records passed to the callback triggered by the sampling of an allocation. *) + type ('minor, 'major) tracker = { + alloc_minor: allocation -> 'minor option; + alloc_major: allocation -> 'major option; + promote: 'minor -> 'major option; + dealloc_minor: 'minor -> unit; + dealloc_major: 'major -> unit; + } + (** + A [('minor, 'major) tracker] describes how memprof should track + sampled blocks over their lifetime, keeping a user-defined piece + of metadata for each of them: ['minor] is the type of metadata + to keep for minor blocks, and ['major] the type of metadata + for major blocks. + + If an allocation-tracking or promotion-tracking function returns [None], + memprof stops tracking the corresponding value. + *) + + val null_tracker: ('minor, 'major) tracker + (** Default callbacks simply return [None] or [()] *) + val start : sampling_rate:float -> ?callstack_size:int -> - ?minor_alloc_callback:(allocation -> 'minor option) -> - ?major_alloc_callback:(allocation -> 'major option) -> - ?promote_callback:('minor -> 'major option) -> - ?minor_dealloc_callback:('minor -> unit) -> - ?major_dealloc_callback:('major -> unit) -> - unit -> unit + ('minor, 'major) tracker -> + unit (** Start the sampling with the given parameters. Fails if sampling is already active. @@ -478,14 +495,10 @@ module Memprof : The parameter [callstack_size] is the length of the callstack recorded at every sample. Its default is [max_int]. - The parameters *[_callback] are functions called when an event - occurs on a sampled block. If such a callback returns [None], - then the tracking of this particular block is cancelled. If - they return [Some v], then the value [v] will be passed to the - next callback for this block. Default callbacks simply return - [None] or [()]. + The parameter [tracker] determines how to track sampled blocks + over their lifetime in the minor and major heap. - The sampling is temporarily disabled when calling a callback + Sampling is temporarily disabled when calling a callback for the current thread. So they do not need to be reentrant if the program is single-threaded. However, if threads are used, it is possible that a context switch occurs during a callback, |