160 lines
4.4 KiB
Awk
Executable File
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");
|
|
}
|
|
}
|