Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve benchmarks #1034

Merged
merged 4 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ publish-docs:
test :
dune runtest

# ODOC_BENCHMARK=true will cause the driver to build a larger set of libraries
# containing more edge cases.
.PHONY : bench
bench:
@dune build @bench
@ODOC_BENCHMARK=true dune build @bench
panglesd marked this conversation as resolved.
Show resolved Hide resolved

.PHONY : coverage
coverage :
Expand Down
176 changes: 93 additions & 83 deletions doc/driver.mld
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ let extra_deps = [
"base_quickcheck";
"ppx_sexp_conv";
"ppx_hash";
"core";
]

let dep_libraries =
Expand Down Expand Up @@ -776,12 +777,16 @@ Some code to analyze the list of executed commands:
{[
(** Return the list of executed commands where the first argument was [cmd]. *)
let filter_commands cmd =
List.filter
(fun c ->
match Bos.Cmd.to_list c.cmd with
| _ :: cmd' :: _ -> cmd = cmd'
| _ -> false)
!commands
match
List.filter
(fun c ->
match Bos.Cmd.to_list c.cmd with
| _ :: cmd' :: _ -> cmd = cmd'
| _ -> false)
!commands
with
| [] -> failwith ("No commands run for " ^ cmd)
| (_ :: _) as cmds -> cmds

(** Returns the [k] commands that took the most time for a given subcommand. *)
let k_longest_commands cmd k =
Expand Down Expand Up @@ -816,99 +821,104 @@ This last block analyze the running times so that they can be submitted to
(* *)
#require "yojson" ;;

let rec compute_min_max_avg min_ max_ total count = function
| [] -> (min_, max_, total /. float count, count)
| hd :: tl ->
compute_min_max_avg (min min_ hd) (max max_ hd) (total +. hd) (count + 1) tl

let compute_min_max_avg = function
| [] -> assert false
| hd :: tl -> compute_min_max_avg hd hd hd 1 tl

(** Analyze the running time of a command. *)
let compute_metric_cmd cmd =
let rec compute min_ max_ total count = function
| [] -> (min_, max_, total /. float count, count)
| hd :: tl ->
compute (min min_ hd.time) (max max_ hd.time) (total +. hd.time) (count + 1) tl
in
match filter_commands cmd with
| [] -> failwith ("No commands run for " ^ cmd)
| hd :: tl ->
let min, max, avg, count = compute hd.time hd.time hd.time 1 tl in
let cmds = filter_commands cmd in
let times = List.map (fun c -> c.time) cmds in
let min, max, avg, count = compute_min_max_avg times in
[
`Assoc
[
`Assoc
[
("name", `String ("total-" ^ cmd));
("value", `Int count);
( "description",
`String ("Number of time 'odoc " ^ cmd ^ "' has run.") );
];
`Assoc
[
("name", `String ("time-" ^ cmd));
( "value",
`Assoc
[
("min", `Float min); ("max", `Float max); ("avg", `Float avg);
] );
("units", `String "s");
("description", `String ("Time taken by 'odoc " ^ cmd ^ "'"));
("trend", `String "lower-is-better");
];
]
("name", `String ("total-" ^ cmd));
("value", `Int count);
( "description",
`String ("Number of time 'odoc " ^ cmd ^ "' has run.") );
];
`Assoc
[
("name", `String ("time-" ^ cmd));
( "value",
`Assoc
[
("min", `Float min); ("max", `Float max); ("avg", `Float avg);
] );
("units", `String "s");
("description", `String ("Time taken by 'odoc " ^ cmd ^ "'"));
("trend", `String "lower-is-better");
];
]

(** Analyze the size of files produced by a command. *)
let compute_produced_cmd cmd =
let output_file_size c =
match c.output_file with
| Some f -> (
match Bos.OS.Path.stat f with
| Ok st -> Some st.Unix.st_size
| Ok st -> Some (float st.Unix.st_size)
| Error _ -> None)
| None -> None
in
let rec compute min_ max_ total count = function
| [] -> (min_, max_, int_of_float (total /. float count), count)
| size :: tl ->
compute (min min_ size) (max max_ size) (total +. float size) (count + 1) tl
in
match List.filter_map output_file_size (filter_commands cmd) with
| [] -> failwith ("No commands run for " ^ cmd)
| size0 :: tl ->
let min, max, avg, count = compute size0 size0 (float size0) 1 tl in
let sizes = List.filter_map output_file_size (filter_commands cmd) in
let min, max, avg, count = compute_min_max_avg sizes in
let min = int_of_float min in
let max = int_of_float max in
let avg = int_of_float avg in
[
`Assoc
[
`Assoc
[
("name", `String ("produced-total-" ^ cmd));
("value", `Int count);
( "description",
`String ("Number of file produced by 'odoc " ^ cmd ^ "'") );
];
`Assoc
[
("name", `String ("produced-size-" ^ cmd));
( "value",
`Assoc
[
("min", `Int min); ("max", `Int max); ("avg", `Int avg);
] );
("units", `String "b");
( "description",
`String ("Size of file produced by 'odoc " ^ cmd ^ "'") );
("trend", `String "lower-is-better");
];
]

(** Analyze the size of files produced by a command. *)
("name", `String ("produced-total-" ^ cmd));
("value", `Int count);
( "description",
`String ("Number of file produced by 'odoc " ^ cmd ^ "'") );
];
`Assoc
[
("name", `String ("produced-size-" ^ cmd));
( "value",
`Assoc
[
("min", `Int min); ("max", `Int max); ("avg", `Int avg);
] );
("units", `String "b");
( "description",
`String ("Size of file produced by 'odoc " ^ cmd ^ "'") );
("trend", `String "lower-is-better");
];
]

(** Analyze the running time of the slowest commands. *)
let compute_longest_cmd cmd =
match k_longest_commands cmd 1 with
| hd :: _ ->
let k = 5 in
let cmds = k_longest_commands cmd k in
let times = List.map (fun c -> c.time) cmds in
let min, max, avg, _count = compute_min_max_avg times in
[
`Assoc
[
`Assoc
[
("name", `String ("longest-" ^ cmd));
("value", `Float hd.time);
("units", `String "s");
( "description",
`String
("Time taken by the longest invokation of 'odoc " ^ cmd ^ "'")
);
("trend", `String "lower-is-better");
];
]
| [] -> []
("name", `String ("longest-" ^ cmd));
( "value",
`Assoc
[
("min", `Float min); ("max", `Float max); ("avg", `Float avg);
] );
("units", `String "s");
( "description",
`String
(Printf.sprintf "Time taken by the %d longest calls to 'odoc %s'"
k cmd)
);
("trend", `String "lower-is-better");
];
]

let metrics =
compute_metric_cmd "compile"
Expand Down
4 changes: 3 additions & 1 deletion doc/dune
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
(glob_files library_mlds/*)
(glob_files examples/*.ml*))
(action
(run ocaml-mdx-test --force-output %{dep:driver.mld})))
(progn
(write-file driver-benchmarks.json "")
(run ocaml-mdx-test --force-output %{dep:driver.mld}))))

(rule
(alias docgen)
Expand Down
1 change: 1 addition & 0 deletions doc/library_mlds/core.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{0 core}
1 change: 1 addition & 0 deletions odoc-bench.opam
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ depends: [
"bos"
"yojson" {>= "1.6.0"}
"mdx" {>= "2.3.0"}
"core"
]
Loading