[backend] a module for recording simple counters-based stats

Summary:
Use it to trace summary stats. It will be used more/better in future
diffs that aggregates stats across parallel workers.

Reviewed By: ezgicicek

Differential Revision: D16358868

fbshipit-source-id: 764614153
master
Jules Villard 5 years ago committed by Facebook Github Bot
parent 73179f7182
commit deb9afe121

@ -0,0 +1,93 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
type t =
{ mutable summary_file_try_load: int
; mutable summary_read_from_disk: int
; mutable summary_cache_hits: int
; mutable summary_cache_misses: int
; mutable summary_has_model_queries: int }
let global_stats =
{ summary_file_try_load= 0
; summary_read_from_disk= 0
; summary_cache_hits= 0
; summary_cache_misses= 0
; summary_has_model_queries= 0 }
let get () = global_stats
let incr_summary_file_try_load () =
global_stats.summary_file_try_load <- global_stats.summary_file_try_load + 1
let incr_summary_read_from_disk () =
global_stats.summary_read_from_disk <- global_stats.summary_read_from_disk + 1
let incr_summary_cache_hits () =
global_stats.summary_cache_hits <- global_stats.summary_cache_hits + 1
let incr_summary_cache_misses () =
global_stats.summary_cache_misses <- global_stats.summary_cache_misses + 1
let incr_summary_has_model_queries () =
global_stats.summary_has_model_queries <- global_stats.summary_has_model_queries + 1
let copy from ~into =
(* so we don't forget to add new fields to [copy] *)
let[@warning "+9"] { summary_file_try_load
; summary_read_from_disk
; summary_cache_hits
; summary_cache_misses
; summary_has_model_queries } =
from
in
into.summary_file_try_load <- summary_file_try_load ;
into.summary_read_from_disk <- summary_read_from_disk ;
into.summary_cache_hits <- summary_cache_hits ;
into.summary_cache_misses <- summary_cache_misses ;
into.summary_has_model_queries <- summary_has_model_queries
let initial =
{ summary_file_try_load= 0
; summary_read_from_disk= 0
; summary_cache_hits= 0
; summary_cache_misses= 0
; summary_has_model_queries= 0 }
let reset () = copy initial ~into:global_stats
let pp f stats =
(* make sure we print all the fields *)
let[@warning "+9"] { summary_file_try_load
; summary_read_from_disk
; summary_cache_hits
; summary_cache_misses
; summary_has_model_queries } =
stats
in
let pp_hit_percent hit miss f =
let total = hit + miss in
if Int.equal total 0 then F.pp_print_string f "N/A%%"
else F.fprintf f "%d%%" (hit * 100 / total)
in
F.fprintf f
"@[Backend stats:@\n\
@[<v2> file_try_load= %d@;read_from_disk= %d@;cache_hits= %d (%t)@;cache_misses= \
%d@;has_model_queries= %d@;@]@]@."
summary_file_try_load summary_read_from_disk summary_cache_hits
(pp_hit_percent summary_cache_hits summary_cache_misses)
summary_cache_misses summary_has_model_queries

@ -0,0 +1,32 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
(** collect statistics about backend/analysis operations *)
type t
val incr_summary_file_try_load : unit -> unit
(** a query to the filesystem attempting to load a summary file *)
val incr_summary_read_from_disk : unit -> unit
(** a summary file is deserialized from disk *)
val incr_summary_cache_hits : unit -> unit
val incr_summary_cache_misses : unit -> unit
val incr_summary_has_model_queries : unit -> unit
(** someone asked if a proc name has a biabduction model *)
val reset : unit -> unit
(** reset all stats *)
val get : unit -> t
(** get the stats so far *)
val pp : Format.formatter -> t -> unit

@ -168,6 +168,7 @@ module OnDisk = struct
let has_model pname = let has_model pname =
BackendStats.incr_summary_has_model_queries () ;
Sys.file_exists (DB.filename_to_string (specs_models_filename pname)) = `Yes Sys.file_exists (DB.filename_to_string (specs_models_filename pname)) = `Yes
@ -176,7 +177,12 @@ module OnDisk = struct
(** Load procedure summary from the given file *) (** Load procedure summary from the given file *)
let load_from_file specs_file = Serialization.read_from_file summary_serializer specs_file let load_from_file specs_file =
BackendStats.incr_summary_file_try_load () ;
let opt = Serialization.read_from_file summary_serializer specs_file in
if Option.is_some opt then BackendStats.incr_summary_read_from_disk () ;
opt
(** Load procedure summary for the given procedure name and update spec table *) (** Load procedure summary for the given procedure name and update spec table *)
let load_summary_to_spec_table = let load_summary_to_spec_table =
@ -209,8 +215,10 @@ module OnDisk = struct
let get proc_name = let get proc_name =
match Typ.Procname.Hash.find cache proc_name with match Typ.Procname.Hash.find cache proc_name with
| summary -> | summary ->
BackendStats.incr_summary_cache_hits () ;
Some summary Some summary
| exception Caml.Not_found -> | exception Caml.Not_found ->
BackendStats.incr_summary_cache_misses () ;
load_summary_to_spec_table proc_name load_summary_to_spec_table proc_name
@ -271,8 +279,10 @@ module OnDisk = struct
let reset_all ~filter () = let reset_all ~filter () =
let reset proc_name = let reset proc_name =
let filename = specs_filename_of_procname proc_name in let filename = specs_filename_of_procname proc_name in
BackendStats.incr_summary_file_try_load () ;
Serialization.read_from_file summary_serializer filename Serialization.read_from_file summary_serializer filename
|> Option.iter ~f:(fun summary -> |> Option.iter ~f:(fun summary ->
BackendStats.incr_summary_read_from_disk () ;
let blank_summary = reset summary.proc_desc in let blank_summary = reset summary.proc_desc in
Serialization.write_to_file summary_serializer filename ~data:blank_summary ) Serialization.write_to_file summary_serializer filename ~data:blank_summary )
in in

@ -14,6 +14,7 @@ type 'a task_generator = 'a ProcessPool.task_generator
let fork_protect ~f x = let fork_protect ~f x =
(* this is needed whenever a new process is started *) (* this is needed whenever a new process is started *)
BackendStats.reset () ;
Epilogues.reset () ; Epilogues.reset () ;
EventLogger.prepare () ; EventLogger.prepare () ;
L.reset_formatters () ; L.reset_formatters () ;
@ -21,6 +22,9 @@ let fork_protect ~f x =
(* get different streams of random numbers in each fork, in particular to lessen contention in (* get different streams of random numbers in each fork, in particular to lessen contention in
`Filename.mk_temp` *) `Filename.mk_temp` *)
Random.self_init () ; Random.self_init () ;
Epilogues.register
~f:(fun () -> L.debug Analysis Quiet "%a@." BackendStats.pp (BackendStats.get ()))
~description:"dumping summaries stats" ;
f x f x

Loading…
Cancel
Save