#!/bin/awk -f #************************************************************************** #* * #* OCaml * #* * #* Damien Doligez, Jane Street Group, LLC * #* * #* Copyright 2014 Institut National de Recherche en Informatique et * #* en Automatique. * #* * #* All rights reserved. This file is distributed under the terms of * #* the GNU Lesser General Public License version 2.1, with the * #* special exception on linking described in the file LICENSE. * #* * #************************************************************************** # usage: # ocaml-instr-report { file ... } # generate a report from the data files (or stdin if no file is given) function short(n, kind, i, r){ for (i = 0; i < 5; i++){ if (n < 1000) break; n /= 1000; } r = sprintf ("%f", n); if (index(r, ".") == 3){ r = substr(r, 1, 2); }else{ r = substr(r, 1, 3); } return sprintf("%s%s", r, units[kind,i]); } function add(limit){ lim[nscales] = limit; scale["t",nscales] = short(limit, "t"); scale["n",nscales] = short(limit, "n"); ++ nscales; } # kind is "t" (for timer) or "n" (for number) # events are simply a special kind of timer BEGIN { units["t",0] = "ns"; units["t",1] = "us"; units["t",2] = "ms"; units["t",3] = "s"; units["t",4] = "ks"; units["t",5] = "Ms"; units["n",0] = ""; units["n",1] = "k"; units["n",2] = "M"; units["n",3] = "G"; units["n",4] = "T"; units["n",5] = "P"; nscales=0; add(0); for (mul = 100; mul < 10000000000; mul *= 10){ add(mul); add(2.2 * mul); add(4.7 * mul); } } function store(value, tag) { ++ total[tag]; for (i = 0; i < nscales; i++){ if (value <= lim[i]){ ++ bin[tag, lim[i]]; val[tag, lim[i]] = value; return; } } ++ bin[tag, "off-scale"]; val[tag, "off-scale"] = value; } $1 == "@@" && $4 ~ /@/ { total[$4] += $3; } $1 == "@@" && $4 ~ /#/ { store($3, $4); } $1 == "@@" { store($3 - $2, $4); } function display(n, val, kind, i) { graph_width = 35; if (n > 0){ for (i = 0; i < log (n) / log (2); i++){ printf("#"); } if (n == 1){ printf(" %-6d", n); printf ("%-*s", graph_width - 7 - i, sprintf("(%s)", short(val, kind))); }else{ printf(" %-*d", graph_width - 1 - i, n); } }else{ printf("%*s", graph_width, ""); } } END { n = asorti(total,tags); total_alloc = 0; for (i = 1; i <= n; i++){ t = tags[i]; if (t ~ /^alloc/) total_alloc += total[t]; } for (i = 1; i <= n; i++){ t = tags[i]; if (t ~ /#/){ kind = "n"; # number }else if (t ~ /@/){ kind = "e"; # event }else{ kind = "t"; # timer } if (kind == "e"){ printf ("==== %-12s:%9d", t, total[t]); if (t ~ /^alloc/){ cumul += total[t] / total_alloc; printf(" (%6.2f%%)", cumul * 100); } printf ("\n"); continue; }else{ printf ("==== %s: %d\n", t, total[t]); } num = bin[t,0]; found = num; if (num == total[t] && kind == "t"){ /* nothing */ }else if (num > 0){ printf (" 0: "); display(bin[t,0], val[t, 0], kind); printf ("%6.2f%%\n", found * 100 / total[t]); } for (j = 1; j < nscales; j++){ if (found == total[t]) break; num = bin [t, lim[j]]; found += num; if (found > 0){ printf ("%5s..%-5s: ", scale[kind,j-1], scale[kind,j]); display(num, val[t, lim[j]], kind); printf ("%6.2f%%\n", found * 100 / total[t]); } } num = bin[t, "off-scale"]; if (num != 0){ printf (" off scale : "); display(bin[t, "off-scale"], val[t, "off-scale"]); printf ("\n"); } printf ("====\n"); } }