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
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 ())
|
|
)
|