ocaml/tools/ocaml-instr-report

160 lines
4.4 KiB
Awk
Executable File

#!/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 Q Public License version 1.0. #
# #
#########################################################################
# 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");
}
}