mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-10 13:14:09 -05:00
feat: add profiling system based on TEF
- a `Sidekick_util.Profile` module, deps-free - an optional sidekick.tef library that needs unix+mtime
This commit is contained in:
parent
23dcf79560
commit
fafb001934
13 changed files with 204 additions and 5 deletions
|
|
@ -18,6 +18,7 @@ depends: [
|
||||||
"smtlib-utils" { >= "0.1" & < "0.3" }
|
"smtlib-utils" { >= "0.1" & < "0.3" }
|
||||||
"sidekick" { = version }
|
"sidekick" { = version }
|
||||||
"menhir"
|
"menhir"
|
||||||
|
"mtime"
|
||||||
"msat" { >= "0.8" < "0.9" }
|
"msat" { >= "0.8" < "0.9" }
|
||||||
"ocaml" { >= "4.03" }
|
"ocaml" { >= "4.03" }
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,7 @@ module Make(A : ARG) : S with module A = A = struct
|
||||||
|
|
||||||
let final_check_ (self:state) si (acts:SI.actions) (trail:_ Iter.t) : unit =
|
let final_check_ (self:state) si (acts:SI.actions) (trail:_ Iter.t) : unit =
|
||||||
Log.debug 5 "(th-lra.final-check)";
|
Log.debug 5 "(th-lra.final-check)";
|
||||||
|
Profile.with_ "lra.final-check" @@ fun () ->
|
||||||
let simplex = SimpSolver.create self.gensym in
|
let simplex = SimpSolver.create self.gensym in
|
||||||
encode_neq self si acts trail;
|
encode_neq self si acts trail;
|
||||||
(* first, add definitions *)
|
(* first, add definitions *)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
(public_name sidekick)
|
(public_name sidekick)
|
||||||
(package sidekick-bin)
|
(package sidekick-bin)
|
||||||
(libraries containers iter result msat sidekick.core sidekick-arith.base-term
|
(libraries containers iter result msat sidekick.core sidekick-arith.base-term
|
||||||
sidekick.msat-solver sidekick-bin.smtlib)
|
sidekick.msat-solver sidekick-bin.smtlib sidekick.tef)
|
||||||
(flags :standard -safe-string -color always -open Sidekick_util))
|
(flags :standard -safe-string -color always -open Sidekick_util))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,8 @@ let check_limits () =
|
||||||
raise Out_of_space
|
raise Out_of_space
|
||||||
|
|
||||||
let main () =
|
let main () =
|
||||||
|
Sidekick_tef.setup();
|
||||||
|
at_exit Sidekick_tef.teardown;
|
||||||
CCFormat.set_color_default true;
|
CCFormat.set_color_default true;
|
||||||
(* Administrative duties *)
|
(* Administrative duties *)
|
||||||
Arg.parse argspec input_file usage;
|
Arg.parse argspec input_file usage;
|
||||||
|
|
|
||||||
|
|
@ -587,12 +587,15 @@ module Make(A : ARG)
|
||||||
let add_clause (self:t) (c:Atom.t IArray.t) : unit =
|
let add_clause (self:t) (c:Atom.t IArray.t) : unit =
|
||||||
Stat.incr self.count_clause;
|
Stat.incr self.count_clause;
|
||||||
Log.debugf 50 (fun k->k "(@[solver.add-clause@ %a@])" (Util.pp_iarray Atom.pp) c);
|
Log.debugf 50 (fun k->k "(@[solver.add-clause@ %a@])" (Util.pp_iarray Atom.pp) c);
|
||||||
Sat_solver.add_clause_a self.solver (c:> Atom.t array) P.default
|
let pb = Profile.begin_ "add-clause" in
|
||||||
|
Sat_solver.add_clause_a self.solver (c:> Atom.t array) P.default;
|
||||||
|
Profile.exit pb
|
||||||
|
|
||||||
let add_clause_l self c = add_clause self (IArray.of_list c)
|
let add_clause_l self c = add_clause self (IArray.of_list c)
|
||||||
|
|
||||||
let mk_model (self:t) (lits:lit Iter.t) : Model.t =
|
let mk_model (self:t) (lits:lit Iter.t) : Model.t =
|
||||||
Log.debug 1 "(smt.solver.mk-model)";
|
Log.debug 1 "(smt.solver.mk-model)";
|
||||||
|
Profile.with_ "msat-solver.mk-model" @@ fun () ->
|
||||||
let module M = Term.Tbl in
|
let module M = Term.Tbl in
|
||||||
let m = M.create 128 in
|
let m = M.create 128 in
|
||||||
let tst = self.si.tst in
|
let tst = self.si.tst in
|
||||||
|
|
@ -614,6 +617,7 @@ module Make(A : ARG)
|
||||||
|
|
||||||
let solve ?(on_exit=[]) ?(check=true) ?(on_progress=fun _ -> ())
|
let solve ?(on_exit=[]) ?(check=true) ?(on_progress=fun _ -> ())
|
||||||
~assumptions (self:t) : res =
|
~assumptions (self:t) : res =
|
||||||
|
Profile.with_ "msat-solver.solve" @@ fun () ->
|
||||||
let do_on_exit () =
|
let do_on_exit () =
|
||||||
List.iter (fun f->f()) on_exit;
|
List.iter (fun f->f()) on_exit;
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
(** {2 Conversion into {!Term.t}} *)
|
(** {2 Conversion into {!Term.t}} *)
|
||||||
|
|
||||||
module BT = Sidekick_base_term
|
module BT = Sidekick_base_term
|
||||||
|
module Profile = Sidekick_util.Profile
|
||||||
open Sidekick_base_term
|
open Sidekick_base_term
|
||||||
|
|
||||||
[@@@ocaml.warning "-32"]
|
[@@@ocaml.warning "-32"]
|
||||||
|
|
@ -153,8 +154,10 @@ let solve
|
||||||
let on_progress =
|
let on_progress =
|
||||||
if progress then Some (mk_progress()) else None in
|
if progress then Some (mk_progress()) else None in
|
||||||
let res =
|
let res =
|
||||||
|
Profile.with_ "solve" begin fun () ->
|
||||||
Solver.solve ~assumptions ?on_progress s
|
Solver.solve ~assumptions ?on_progress s
|
||||||
(* ?gc ?restarts ?time ?memory ?progress *)
|
(* ?gc ?restarts ?time ?memory ?progress *)
|
||||||
|
end
|
||||||
in
|
in
|
||||||
let t2 = Sys.time () in
|
let t2 = Sys.time () in
|
||||||
Printf.printf "\r"; flush stdout;
|
Printf.printf "\r"; flush stdout;
|
||||||
|
|
@ -176,11 +179,12 @@ let solve
|
||||||
Format.printf "Unsat (%.3f/%.3f/-)@." t1 (t2-.t1);
|
Format.printf "Unsat (%.3f/%.3f/-)@." t1 (t2-.t1);
|
||||||
| Solver.Unsat {proof=Some p;_} ->
|
| Solver.Unsat {proof=Some p;_} ->
|
||||||
if check then (
|
if check then (
|
||||||
Solver.Proof.check p;
|
Profile.with_ "unsat.check" (fun () -> Solver.Proof.check p);
|
||||||
);
|
);
|
||||||
begin match dot_proof with
|
begin match dot_proof with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some file ->
|
| Some file ->
|
||||||
|
Profile.with_ "dot.proof" @@ fun () ->
|
||||||
CCIO.with_out file
|
CCIO.with_out file
|
||||||
(fun oc ->
|
(fun oc ->
|
||||||
Log.debugf 1 (fun k->k "write proof into `%s`" file);
|
Log.debugf 1 (fun k->k "write proof into `%s`" file);
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,6 @@
|
||||||
(public_name sidekick-bin.smtlib)
|
(public_name sidekick-bin.smtlib)
|
||||||
(libraries containers zarith msat sidekick.core sidekick.util
|
(libraries containers zarith msat sidekick.core sidekick.util
|
||||||
sidekick.msat-solver sidekick-arith.base-term sidekick.th-bool-static
|
sidekick.msat-solver sidekick-arith.base-term sidekick.th-bool-static
|
||||||
sidekick.mini-cc sidekick.th-data sidekick-arith.lra msat.backend smtlib-utils)
|
sidekick.mini-cc sidekick.th-data sidekick-arith.lra msat.backend smtlib-utils
|
||||||
|
sidekick.tef)
|
||||||
(flags :standard -warn-error -a+8 -open Sidekick_util))
|
(flags :standard -warn-error -a+8 -open Sidekick_util))
|
||||||
|
|
|
||||||
62
src/tef/Sidekick_tef.ml
Normal file
62
src/tef/Sidekick_tef.ml
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
module P = Sidekick_util.Profile
|
||||||
|
|
||||||
|
let active = lazy (
|
||||||
|
match Sys.getenv "TEF" with
|
||||||
|
| "1"|"true" -> true | _ -> false
|
||||||
|
| exception Not_found -> false
|
||||||
|
)
|
||||||
|
|
||||||
|
let program_start = Mtime_clock.now()
|
||||||
|
|
||||||
|
module Make()
|
||||||
|
: P.BACKEND
|
||||||
|
= struct
|
||||||
|
let first_ = ref true
|
||||||
|
let closed_ = ref false
|
||||||
|
|
||||||
|
let teardown_ oc =
|
||||||
|
if not !closed_ then (
|
||||||
|
closed_ := true;
|
||||||
|
output_char oc ']'; (* close array *)
|
||||||
|
flush oc;
|
||||||
|
close_out_noerr oc
|
||||||
|
)
|
||||||
|
|
||||||
|
(* connection to subprocess writing into the file *)
|
||||||
|
let oc =
|
||||||
|
let oc = Unix.open_process_out "gzip - --stdout > trace.json.gz" in
|
||||||
|
output_char oc '[';
|
||||||
|
at_exit (fun () -> teardown_ oc);
|
||||||
|
oc
|
||||||
|
|
||||||
|
let get_ts () : float =
|
||||||
|
let now = Mtime_clock.now() in
|
||||||
|
Mtime.Span.to_us (Mtime.span program_start now)
|
||||||
|
|
||||||
|
let emit_event ~name ~start ~end_ () : unit =
|
||||||
|
let dur = end_ -. start in
|
||||||
|
let ts = start in
|
||||||
|
let pid = Unix.getpid() in
|
||||||
|
let tid = Thread.id (Thread.self()) in
|
||||||
|
if !first_ then (
|
||||||
|
first_ := false;
|
||||||
|
) else (
|
||||||
|
output_string oc ",\n";
|
||||||
|
);
|
||||||
|
Printf.fprintf oc
|
||||||
|
{json|{"pid": %d,"cat":"","tid": %d,"dur": %.2f,"ts": %.2f,"name":"%s","ph":"X"}|json}
|
||||||
|
pid tid dur ts name;
|
||||||
|
flush oc
|
||||||
|
|
||||||
|
let teardown () = teardown_ oc
|
||||||
|
end
|
||||||
|
|
||||||
|
let setup_ = lazy (
|
||||||
|
let lazy active = active in
|
||||||
|
let b = if active then Some (module Make() : P.BACKEND) else None in
|
||||||
|
P.Control.setup b
|
||||||
|
)
|
||||||
|
|
||||||
|
let setup () = Lazy.force setup_
|
||||||
|
let teardown = P.Control.teardown
|
||||||
10
src/tef/Sidekick_tef.mli
Normal file
10
src/tef/Sidekick_tef.mli
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
(** {1 Tracing Event Format}
|
||||||
|
|
||||||
|
A nice profiling format based on json, useful for visualizing what goes on.
|
||||||
|
See https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/
|
||||||
|
*)
|
||||||
|
|
||||||
|
val setup : unit -> unit
|
||||||
|
|
||||||
|
val teardown : unit -> unit
|
||||||
8
src/tef/dune
Normal file
8
src/tef/dune
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
(library
|
||||||
|
(name sidekick_tef)
|
||||||
|
(public_name sidekick.tef)
|
||||||
|
(synopsis "profiling backend based on TEF")
|
||||||
|
(optional)
|
||||||
|
(flags :standard -warn-error -a+8)
|
||||||
|
(libraries sidekick.util unix threads mtime mtime.clock.os))
|
||||||
74
src/util/Profile.ml
Normal file
74
src/util/Profile.ml
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
module type BACKEND = sig
|
||||||
|
val get_ts : unit -> float
|
||||||
|
|
||||||
|
val emit_event :
|
||||||
|
name : string ->
|
||||||
|
start : float ->
|
||||||
|
end_ : float ->
|
||||||
|
unit ->
|
||||||
|
unit
|
||||||
|
|
||||||
|
val teardown : unit -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
type backend = (module BACKEND)
|
||||||
|
|
||||||
|
type probe =
|
||||||
|
| No_probe
|
||||||
|
| Probe of {
|
||||||
|
name: string;
|
||||||
|
start: float;
|
||||||
|
}
|
||||||
|
|
||||||
|
(* where to print events *)
|
||||||
|
let out_ : backend option ref = ref None
|
||||||
|
|
||||||
|
let begin_with_ (module B:BACKEND) name : probe =
|
||||||
|
Probe {name; start=B.get_ts ()}
|
||||||
|
|
||||||
|
let[@inline] begin_ name : probe =
|
||||||
|
match !out_ with
|
||||||
|
| None -> No_probe
|
||||||
|
| Some b -> begin_with_ b name
|
||||||
|
|
||||||
|
(* slow path *)
|
||||||
|
let exit_full_ (module B : BACKEND) name start =
|
||||||
|
let now = B.get_ts() in
|
||||||
|
B.emit_event ~name ~start ~end_:now ()
|
||||||
|
|
||||||
|
let exit_with_ b pb =
|
||||||
|
match pb with
|
||||||
|
| No_probe -> ()
|
||||||
|
| Probe {name; start} -> exit_full_ b name start
|
||||||
|
|
||||||
|
let[@inline] exit pb =
|
||||||
|
match pb, !out_ with
|
||||||
|
| Probe {name;start}, Some b -> exit_full_ b name start
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
|
let[@inline] with_ name f =
|
||||||
|
match !out_ with
|
||||||
|
| None -> f()
|
||||||
|
| Some b ->
|
||||||
|
let pb = begin_with_ b name in
|
||||||
|
try
|
||||||
|
let x = f() in
|
||||||
|
exit_with_ b pb;
|
||||||
|
x
|
||||||
|
with e ->
|
||||||
|
exit_with_ b pb;
|
||||||
|
raise e
|
||||||
|
|
||||||
|
module Control = struct
|
||||||
|
let setup b =
|
||||||
|
assert (!out_ = None);
|
||||||
|
out_ := b
|
||||||
|
|
||||||
|
let teardown () =
|
||||||
|
match !out_ with
|
||||||
|
| None -> ()
|
||||||
|
| Some (module B) ->
|
||||||
|
out_ := None;
|
||||||
|
B.teardown()
|
||||||
|
end
|
||||||
31
src/util/Profile.mli
Normal file
31
src/util/Profile.mli
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
(** {1 Profiling probes} *)
|
||||||
|
|
||||||
|
type probe
|
||||||
|
|
||||||
|
val begin_ : string -> probe
|
||||||
|
|
||||||
|
val exit : probe -> unit
|
||||||
|
|
||||||
|
val with_ : string -> (unit -> 'a) -> 'a
|
||||||
|
|
||||||
|
module type BACKEND = sig
|
||||||
|
val get_ts : unit -> float
|
||||||
|
|
||||||
|
val emit_event :
|
||||||
|
name : string ->
|
||||||
|
start : float ->
|
||||||
|
end_ : float ->
|
||||||
|
unit ->
|
||||||
|
unit
|
||||||
|
|
||||||
|
val teardown : unit -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
type backend = (module BACKEND)
|
||||||
|
|
||||||
|
module Control : sig
|
||||||
|
val setup : backend option -> unit
|
||||||
|
|
||||||
|
val teardown : unit -> unit
|
||||||
|
end
|
||||||
|
|
@ -12,3 +12,4 @@ module Intf = Intf
|
||||||
module Bag = Bag
|
module Bag = Bag
|
||||||
module Stat = Stat
|
module Stat = Stat
|
||||||
module Hash = Hash
|
module Hash = Hash
|
||||||
|
module Profile = Profile
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue