summaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
authorGabriel Scherer <gabriel.scherer@gmail.com>2020-01-21 21:42:03 +0100
committerGabriel Scherer <gabriel.scherer@gmail.com>2020-04-01 16:37:28 +0200
commitff6b20098f7f51758d78546af4bb8747cdc8c9f4 (patch)
treebcfe6ca8ad604356d327a9efd4df9564c6fe77f7 /stdlib
parente10e2bfa992c977572ce9dda82ba22b449f54e81 (diff)
downloadocaml-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.ml36
-rw-r--r--stdlib/gc.mli39
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,