You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
6.6 KiB

(*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
(** Performance Statistics gathering and reporting *)
open! Utils
type perf_stats = {
rtime : float;
utime : float;
stime : float;
cutime : float;
cstime : float;
minor_gb : float;
promoted_gb : float;
major_gb : float;
allocated_gb : float;
minor_collections : int;
major_collections : int;
compactions : int;
top_heap_gb : float;
stack_kb : float;
minor_heap_kb : float;
attributes_table : AttributesTable.t;
}
let to_json ps =
let attributes_table = AttributesTable.stats () in
`Assoc [
("rtime", `Float ps.rtime);
("utime", `Float ps.utime);
("stime", `Float ps.stime);
("cutime", `Float ps.cutime);
("cstime", `Float ps.cstime);
("minor_gb", `Float ps.minor_gb);
("promoted_gb", `Float ps.promoted_gb);
("major_gb", `Float ps.major_gb);
("allocated_gb", `Float ps.allocated_gb);
("minor_collections", `Int ps.minor_collections);
("major_collections", `Int ps.major_collections);
("compactions", `Int ps.compactions);
("top_heap_gb", `Float ps.top_heap_gb);
("stack_kb", `Float ps.stack_kb);
("minor_heap_kb", `Float ps.minor_heap_kb);
("attributes_table", AttributesTable.to_json attributes_table);
]
let from_json json =
let open Yojson.Basic.Util in
{
rtime = json |> member "rtime" |> to_float;
utime = json |> member "utime" |> to_float;
stime = json |> member "stime" |> to_float;
cutime = json |> member "cutime" |> to_float;
cstime = json |> member "cstime" |> to_float;
minor_gb = json |> member "minor_gb" |> to_float;
promoted_gb = json |> member "promoted_gb" |> to_float;
major_gb = json |> member "major_gb" |> to_float;
allocated_gb = json |> member "allocated_gb" |> to_float;
minor_collections = json |> member "minor_collections" |> to_int;
major_collections = json |> member "major_collections" |> to_int;
compactions = json |> member "compactions" |> to_int;
top_heap_gb = json |> member "top_heap_gb" |> to_float;
stack_kb = json |> member "stack_kb" |> to_float;
minor_heap_kb = json |> member "minor_heap_kb" |> to_float;
attributes_table =
json |> member "attributes_table" |> AttributesTable.from_json;
}
let aggregate s =
let mk_stats f = StatisticsToolbox.compute_statistics (IList.map f s) in
let aggr_rtime = mk_stats (fun stats -> stats.rtime) in
let aggr_utime = mk_stats (fun stats -> stats.utime) in
let aggr_stime = mk_stats (fun stats -> stats.stime) in
let aggr_cutime = mk_stats (fun stats -> stats.cutime) in
let aggr_cstime = mk_stats (fun stats -> stats.cstime) in
let aggr_minor_gb = mk_stats (fun stats -> stats.minor_gb) in
let aggr_promoted_gb = mk_stats (fun stats -> stats.promoted_gb) in
let aggr_major_gb = mk_stats (fun stats -> stats.major_gb) in
let aggr_allocated_gb = mk_stats (fun stats -> stats.allocated_gb) in
let aggr_minor_collections = mk_stats (fun stats -> float_of_int stats.minor_collections) in
let aggr_major_collections = mk_stats (fun stats -> float_of_int stats.major_collections) in
let aggr_compactions = mk_stats (fun stats -> float_of_int stats.compactions) in
let aggr_top_heap_gb = mk_stats (fun stats -> stats.top_heap_gb) in
let aggr_stack_kb = mk_stats (fun stats -> stats.stack_kb) in
let aggr_minor_heap_kb = mk_stats (fun stats -> stats.minor_heap_kb) in
let aggr_attributes_table =
AttributesTable.aggregate (IList.map (fun stats -> stats.attributes_table) s) in
`Assoc [
("rtime", StatisticsToolbox.to_json aggr_rtime);
("utime", StatisticsToolbox.to_json aggr_utime);
("stime", StatisticsToolbox.to_json aggr_stime);
("cutime", StatisticsToolbox.to_json aggr_cutime);
("cstime", StatisticsToolbox.to_json aggr_cstime);
("minor_gb", StatisticsToolbox.to_json aggr_minor_gb);
("promoted_gb", StatisticsToolbox.to_json aggr_promoted_gb);
("major_gb", StatisticsToolbox.to_json aggr_major_gb);
("allocated_gb", StatisticsToolbox.to_json aggr_allocated_gb);
("minor_collections", StatisticsToolbox.to_json aggr_minor_collections);
("major_collections", StatisticsToolbox.to_json aggr_major_collections);
("compactions", StatisticsToolbox.to_json aggr_compactions);
("top_heap_gb", StatisticsToolbox.to_json aggr_top_heap_gb);
("stack_kb", StatisticsToolbox.to_json aggr_stack_kb);
("minor_heap_kb", StatisticsToolbox.to_json aggr_minor_heap_kb);
("attributes_table", aggr_attributes_table);
]
let stats () =
let words_to_kb n = n *. float_of_int (Sys.word_size / 8) /. 1024. in
let words_to_mb n = words_to_kb n /. 1024. in
let words_to_gb n = words_to_mb n /. 1024. in
let gc_stats = Gc.quick_stat () in
let allocated_words =
gc_stats.minor_words +. gc_stats.major_words -. gc_stats.promoted_words in
let gc_ctrl = Gc.get () in
let exit_timeofday = Unix.gettimeofday () in
let exit_times = Unix.times () in
let at = AttributesTable.stats () in
{
rtime = exit_timeofday -. initial_timeofday;
utime = exit_times.tms_utime -. initial_times.tms_utime;
stime = exit_times.tms_stime -. initial_times.tms_stime;
cutime = exit_times.tms_cutime -. initial_times.tms_cutime;
cstime = exit_times.tms_cstime -. initial_times.tms_cstime;
minor_gb = words_to_gb gc_stats.minor_words;
promoted_gb = words_to_gb gc_stats.promoted_words;
major_gb = words_to_gb gc_stats.major_words;
allocated_gb = words_to_gb allocated_words;
minor_collections = gc_stats.minor_collections;
major_collections = gc_stats.major_collections;
compactions = gc_stats.compactions;
top_heap_gb = words_to_gb (float_of_int gc_stats.top_heap_words);
stack_kb = words_to_kb (float_of_int gc_stats.stack_size);
minor_heap_kb = words_to_kb (float_of_int gc_ctrl.minor_heap_size);
attributes_table = at
}
let register_report_at_exit file =
Pervasives.at_exit (fun () ->
try
let json_stats = to_json (stats ()) in
try
let stats_oc = open_out file in
Yojson.Basic.pretty_to_channel stats_oc json_stats ;
close_out stats_oc
with exc ->
Format.eprintf "Info: failed to write stats to %s@\n%s@\n%s@\n%s@."
file (Printexc.to_string exc) (Yojson.Basic.pretty_to_string json_stats)
(Printexc.get_backtrace ())
with exc ->
Format.eprintf "Info: failed to compute stats for %s@\n%s@\n%s@."
file (Printexc.to_string exc) (Printexc.get_backtrace ())
)