#! /usr/bin/awk -f
#
# Profile CMT commands utilisation in the Makefiles
#
# Usage:
#
# export VERBOSE=1
# export TIME="%U user %S system %e elapsed %P CPU %C (%Xtext+%Ddata %Mmax)k %Iinputs+%Ooutputs (%Fmajor+%Rminor)pagefaults %Wswaps %cswitch %wswitch voluntarily"
# 
# \time cmt br make -j1 cmtexe="'\time ${CMTROOT}/${CMTBIN}/cmt.exe'" >&cmt-br-make-time.log&
# OR
# \time cmt br make -j1 cmtexe="'\time ${CMTROOT}/${CMTBIN}/cmt.exe'" cpp="'\time c++'" cc="'\time cc'" make_shlib="'\time ${CMTROOT}/mgr/cmt_make_shlib_common.sh extract'" >&cmt-br-make-time.log&
#
# ./cmt-make-time-sub-mem-io.awk cmt-br-make-time.log
#
$2 == "user" && $4 == "system" && $6 == "elapsed" {
#if ($9 == "g++") {
  if ($9 ~ /([gc]\+\+|g?cc)$/) {
    gxx_u += $1; gxx_s += $3; gxx_e += $5; gxx_i += 1
    if ($0 ~ /-MM/) {
      dep_u += $1; dep_s += $3; dep_e += $5; dep_i += 1
    }
  }
  else if ($9 ~ /cmt_make_shlib_common\.sh$/) {
    make_shlib_u += $1; make_shlib_s += $3; make_shlib_e += $5; make_shlib_i += 1
  }
  else if ($9 ~ /\/CMT\/(v[[:digit:]]+(r[[:digit:]]+)?(p[[:digit:]]+)?)|HEAD\//) {
    cmt_tot_u += $1; cmt_tot_s += $3; cmt_tot_e += $5; cmt_tot_i += 1
    if ($0 ~ /-f=.+/) fast=1
    else fast=0
    for (i=10; i<=NF; i++) {
      if ($i ~ /-.+/) continue
      k=$i" "$(i+1)
      if (fast == 1) {
	cmt_f_u[k] += $1; cmt_f_s[k] += $3; cmt_f_e[k] += $5; cmt_f_i[k] += 1
      }
      else {
	cmt_u[k] += $1; cmt_s[k] += $3; cmt_e[k] += $5; cmt_i[k] += 1
      }
      break
    }
# Maximum resident set size of the process during its lifetime, in Kilobytes
    _rss_max = $(NF - 6)
    sub("max)k", "", _rss_max)
    rss_max += _rss_max
    rss_max_i += 1

    _major = gensub(/\(([[:digit:]]+)major\+([[:digit:]]+)minor\)pagefaults/, "\\1", "1", $(NF - 4))
    _minor = gensub(/\(([[:digit:]]+)major\+([[:digit:]]+)minor\)pagefaults/, "\\2", "1", $(NF - 4))
    major_pf += _major
    minor_pf += _minor

    cswitch += gensub(/([[:digit:]]+)switch/, "\\1", "1", $(NF - 2))
    wswitch += gensub(/([[:digit:]]+)switch/, "\\1", "1", $(NF - 1))
  }
#  else
#    print "Ignoring command: "$9
}
function prec (val)
{
  if (val >= 100) return 0
  else if (val >= 10) return 1
  else return 2
}
END {
  printf "\nFile(s):"
  for (i = 1; i < ARGC; i++) {
    if (ARGV[i] ~ /^(_|[[:alpha:]])_*[[:alpha:]]*[[:digit:]]*=/) continue
    printf " %s", ARGV[i]
  }
  printf "\n"

  if (make_shlib_i != 0)
    printf "cmt_make_shlib_common.sh[%d]: %.*f user %.*f system %.*f elapsed\n"	\
      , make_shlib_i, prec(make_shlib_u), make_shlib_u, prec(make_shlib_s), make_shlib_s, prec(make_shlib_e), make_shlib_e
  if (gxx_i != 0)
    printf "c++/cc[%d]: %.*f user %.*f system %.*f elapsed\n"	\
      , gxx_i, prec(gxx_u), gxx_u, prec(gxx_s), gxx_s, prec(gxx_e), gxx_e
  if (dep_i != 0)
    printf "dep[%d]: %.*f user %.*f system %.*f elapsed\n"	\
      , dep_i, prec(dep_u), dep_u, prec(dep_s), dep_s, prec(dep_e), dep_e
  printf "cmt[%d]: %.*f user %.*f system %.*f elapsed\n"	\
    , cmt_tot_i, prec(cmt_tot_u), cmt_tot_u, prec(cmt_tot_s), cmt_tot_s, prec(cmt_tot_e), cmt_tot_e
  printf "average rss_max: %.0fk\npage faults: %d major + %d minor\ncontext switch: %d involuntarily + %d voluntarily\n" \
    , (rss_max_i != 0 ? rss_max/rss_max_i : 0), major_pf, minor_pf, cswitch, wswitch
  print "Breakdown:"
  for (n in cmt_f_i) {
    printf "cmt fast [%s] [%d]: %.*f user %.*f system %.*f elapsed\n"	\
      , n, cmt_f_i[n], prec(cmt_f_u[n]), cmt_f_u[n], prec(cmt_f_s[n]), cmt_f_s[n], prec(cmt_f_e[n]), cmt_f_e[n]
    f_i += cmt_f_i[n]; f_u += cmt_f_u[n]; f_s += cmt_f_s[n]; f_e += cmt_f_e[n]
  }
  printf "cmt fast [%d]: %.*f user %.*f system %.*f elapsed\n"	\
    , f_i, prec(f_u), f_u, prec(f_s), f_s, prec(f_e), f_e
  i=0
  for (n in cmt_i) {
    printf "cmt [%s] [%d]: %.*f user %.*f system %.*f elapsed\n"	\
      , n, cmt_i[n], prec(cmt_u[n]), cmt_u[n], prec(cmt_s[n]), cmt_s[n], prec(cmt_e[n]), cmt_e[n]
    i += cmt_i[n]; u += cmt_u[n]; s += cmt_s[n]; e += cmt_e[n]
  }
  printf "cmt [%d]: %.*f user %.*f system %.*f elapsed\n"	\
    , i, prec(u), u, prec(s), s, prec(e), e

  if ($0 != "")
    printf "\n%s\n", $0
}
