How to profile time spent in used library with landmarks

I’m trying to profile my application which uses an opam library lib, using landmarks. I tried to do this:

(*Lib_shim.ml*)
let lib = Landmark.register "lib"
let () = Landmark.enter lib;;
include Lib
let () = Landmark.exit lib
(* dune *)
(library
  (name lib_shim)
  (libraries lib landmarks)
  (instrumentation (backend landmarks))
  (modules lib_shim))

then i open Lib_shim instead of Lib in my application code. but i get only tiny numbers of cycles spent in “lib” which do not reflect the time actually spent inside library functions at all. can i tell landmarks to collectively count all library functions under a common tag?

1 Like

Hi @n4323,

Landmark blocks delimit dynamic program structure, not static structure. The idea is to call enter a landmark block, perform some computation, then exit the block, e.g.:

At the moment, your landmark blocks are profiling the intitialisation of the Lib_shim module: i.e. conceptually you define and enter the "lib" block at the start of initialisation of Lib_shim, define a bunch of functions, then exit the "lib" block, all before your application code has started running. This is probably why you’re seeing such small numbers being reported.

To instrument the function calls themselves, you must do one of:

  • wrap the functions manually with calls into Landmark (see here),
  • use the supplied PPX to do this for you (see here).

Hope this helps.

1 Like

Thanks, this certainly explains what I’m observing. It also seems to imply that I cannot enable landmark profiling unless I also have access to the library source and add annotations there. One way would be to clone the library to a subdirectory within my dune project and add annotations in the local version. This is a bit more detailed than I would want but ok I guess.

Hello !

It also seems to imply that I cannot enable landmark profiling unless I also have access to the library source and add annotations there.

Indeed, you won’t be able to use landmarks to instrument libraries without the source but you can still instrument each entry point of the library (and that should be enough for you).

eg you can do :

[@@@landmark  "auto"]
let f x y = Lib.f x y (** Do not simplify into `let f = Lib.f` as the instrumentation needs to know the "arity of function" to instrument it correctly" *)
let g x y z = Lib.g x y z

The ppx will turn your code into something like :

let lm0 = Landmark.register "f"
let lm1 = Landmark.register "g"
let f x y = 
Landmark.enter lm0; 
try 
  let r = Lib.f x y  in
  Landmark.exit lm0; 
  r
with exn ->
   Landmark.exit lm0;
   raise exn 

let g x y z = 
Landmark.enter lm1; 
try 
  let r = Lib.g x y z  in
  Landmark.exit lm1; 
  r
with exn ->
   Landmark.exit lm1;
   raise exn 
1 Like

Yes that may be the most workable solution. Unfortunately I have a lot of entry points…