(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
open BenchUtil
let die fmt = Printf.kfprintf (fun _ -> exit 1) stderr (fmt^^"\n%!")
let colors = [|"#F08080"; "#EEE8AA"; "#98FB98"|]
let max_data_count = Array.length colors
let htmlescape = let r = Str.regexp "[&<>\"]" in let subst s = match Str.matched_string s with
| "&" -> "&"
| "<" -> "<"
| ">" -> ">"
| "\"" -> """
| _ -> assert false in fun s -> Str.global_substitute r subst s
let percentage ~max:m v =
Q.to_float Q.(v * of_int 100 / m)
let pp_words ~need_comma which w = if w = "0 w"then need_comma, "" else true, (if need_comma then", "else"")^(String.sub w 0 (String.length w - 1))^which^" w"
let pp_collect ~need_comma which c = if c = 0 then need_comma, "" else true, Printf.sprintf "%s%d %s %s"
(if need_comma then", "else"") c which
(if c = 1 then"collection"else"collections")
let pp_memory ch = function
| None -> ()
| Some {major_words; minor_words; major_collect; minor_collect} -> (* need_comma <-> prefix is nontrivial *) let need_comma, minor_words = pp_words ~need_comma:false"minor" minor_words in let need_comma, major_words = pp_words ~need_comma "major" major_words in let need_comma, minor_collect = pp_collect ~need_comma "minor" minor_collect in let need_comma, major_collect = pp_collect ~need_comma "major" major_collect in if need_comma then
Printf.fprintf ch " (%s%s%s%s)" minor_words major_words minor_collect major_collect
let output ch ~vname ~data_files all_data =
let out fmt = Printf.fprintf ch fmt in let ndata = Array.length data_files in
let totals = Array.fold_left (fun acc (_,data) ->
Array.map2 (fun acc d -> Q.add acc d.time.q) acc data)
(Array.make ndata Q.zero)
all_data in
let maxq =
Array.fold_left (fun max (_,data) ->
Array.fold_left (fun max d -> let dq = d.time.q in if Q.lt max dq then dq else max)
max
data)
Q.zero all_data in
let () =
out
{|<html>
<head>
<title>%s</title>
<style>
|} vname in
let () = data_files |> Array.iteri (fun i _ -> let color = colors.(i) in
out
{|.time%d {
background-color: %s;
height: %d%%;
top: %d%%;
z-index: -1;
position: absolute;
opacity: 50%%;
}
|} (i+1) color (100 / ndata) (100 / ndata * i)) in
let () = data_files |> Array.iteri (fun i data_file ->
out "
background-color: %s\">%s (total time: %.3Gs)
\n"
colors.(i)
data_file
(Q.to_float totals.(i))) in
let () = out "\n"in
let () = out "
"
in
let last_seen_line = ref 0 in
let line_id fmt l = if l > !last_seen_line thenbegin
last_seen_line := l;
Printf.fprintf fmt "id=\"L%d\" " l end in
let () = all_data |> Array.iteri (fun j (loc,data) -> let () = out {|<div class="code" title="File: %s
Line: %d
|} vname loc.line in let () = data |> Array.iteri (fun k d ->
out "Time%d: %ss%a\n" (k+1) d.time.str pp_memory d.memory) in let () = out {|">|} in
let () = data |> Array.iteri (fun k d ->
out {|<div class="time%d" style="width: %f%%"></div>|}
(k+1)
(percentage d.time.q ~max:maxq)) in
let text = loc.text in let text = if text <> "" && text.[0] = '\n' thenString.sub text 1 (String.length text - 1) else text in let sublines = String.split_on_char '\n' text in let () = sublines |> List.iteri (fun i line -> let lnum = loc.line + i in
out "%d\">%s\n" line_id lnum lnum (htmlescape line)) in
let () = out "
" in
()) in
let () =
out
{|
</pre>
</body>
</html>
|} in
()
let raw_output ch ~min_diff all_data =
all_data |> Array.iteri @@ fun j (loc,data) -> let d1, d2 = match data with
| [|d1; d2|] -> d1, d2
| _ -> die "-raw-o only supports 2 data files, got %d" (Array.length data) in let diff = Q.(d2.time.q - d1.time.q) in let ignore = Q.lt (Q.abs diff) min_diff in ifnot ignore thenbegin let pdiff = if Q.(equal zero d1.time.q) then Float.infinity else Q.(to_float @@ ((of_int 100 * diff) / d1.time.q)) in (* XXX %.4f makes sense for min_diff=1e-4 but should be smarter for other min_diff *)
Printf.fprintf ch "%s %s %.4f %3.2f%% %d\n"
d1.time.str d2.time.str (Q.to_float diff) pdiff loc.line end
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.