- Added a little program for analyzing the devexec log
This commit is contained in:
274
tcl/analyzedevexeclog
Executable file
274
tcl/analyzedevexeclog
Executable file
@ -0,0 +1,274 @@
|
||||
#!/usr/bin/tclsh
|
||||
#-----------------------------------------------------------------------------
|
||||
# This program analyses a devexec log as written by SICS. It should produce
|
||||
# a list of devices together with the time each device was active
|
||||
# in seconds.
|
||||
#
|
||||
# Mark Koennecke, January 2007
|
||||
#----------------------------------------------------------------------------
|
||||
# Some utility routines for processing an entry in the devexeclog. A line
|
||||
# has the form:
|
||||
# DEVEXEC:OP:DEVICE:SECONDS:NANOSECONDS
|
||||
# This is split into a list and accessor function are provided for various
|
||||
# items
|
||||
#---------------------------------------------------------------------------
|
||||
proc parseLogLine {line} {
|
||||
set l [split $line :]
|
||||
set tst [lindex $l 0]
|
||||
if {[string compare $tst DEVEXEC] != 0} {
|
||||
error "Bad log line: $line"
|
||||
}
|
||||
return [lrange $l 1 end]
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc getLogOp {logList} {
|
||||
return [lindex $logList 0]
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc getLogDevice {logList} {
|
||||
return [lindex $logList 1]
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc getLogSeconds {logList} {
|
||||
return [lindex $logList 2]
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc getLogNanos {logList} {
|
||||
return [lindex $logList 3]
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc getStamp {logList} {
|
||||
return [lrange $logList 2 end]
|
||||
}
|
||||
#==========================================================================
|
||||
proc calcTimeDiff {sec1 nano1 sec2 nano2} {
|
||||
set secSum 0
|
||||
set nanoSum 0
|
||||
if {$sec2 > $sec1} {
|
||||
set nanoSum [expr 1000000 - $nano1]
|
||||
set secSum [expr $sec2 - $sec1 + 1]
|
||||
set nanoSum [expr $nanoSum + $nano2]
|
||||
} elseif {$sec2 == $sec1} {
|
||||
set secSum 0
|
||||
set nanoSum [expr $nano2 - $nano1]
|
||||
} else {
|
||||
error "Bad time order: sec2 should be bigger then sec1"
|
||||
}
|
||||
return [list $secSum $nanoSum]
|
||||
}
|
||||
#=========================================================================
|
||||
# There are two arrays:
|
||||
# One is called devices and holds the device name and the total number
|
||||
# of seconds this device has run. There are special devices:
|
||||
# - nobeam for couting NOBEAM time. This has later to be subtracted from
|
||||
# counting times.
|
||||
# - unallocated time which can not be clearly given to some device
|
||||
# This might happen if the SICServer restarts whilst something is
|
||||
# running.
|
||||
#
|
||||
# The other one is running and holds all the devices which are currently
|
||||
# being run. For each such device a list will be held with seconds
|
||||
# and nanos. At each Start and stop, time differences to the previous
|
||||
# event will be calculated and added to the devices running. If more then
|
||||
# one device is running at a given time, the time will be distributed
|
||||
# equally to all devices.
|
||||
#
|
||||
# There is also a counter for devices which are currently running.
|
||||
#
|
||||
# This section now provides helper functions for dealing with these
|
||||
# arrays
|
||||
#========================================================================
|
||||
set devRun 0
|
||||
set devices(nobeam) 0
|
||||
set devices(unaccounted) 0
|
||||
set sicsRestart 0
|
||||
#------------------------------------------------------------------------
|
||||
proc addToDevice {dev sec nano} {
|
||||
upvar #0 devices devices
|
||||
set totalSec [expr double($sec) + double($nano)/1000000.0]
|
||||
if {[info exists devices($dev)] } {
|
||||
set devices($dev) [expr $devices($dev) + $totalSec]
|
||||
} else {
|
||||
set devices($dev) $totalSec
|
||||
}
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc addToRunning {dev sec nano} {
|
||||
upvar #0 running running devRun devRun
|
||||
if {[info exists running($dev)] } {
|
||||
set l $running($dev)
|
||||
set newSec [expr double([lindex $l 0]) + double($sec)]
|
||||
set newNano [expr double([lindex $l 1]) + double($nano)]
|
||||
set running($dev) [list $newSec $newNano]
|
||||
} else {
|
||||
set running($dev) [list $sec $nano]
|
||||
incr devRun
|
||||
}
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc stopRunning {dev} {
|
||||
upvar #0 running running devRun devRun devices devices
|
||||
set l $running($dev)
|
||||
addToDevice $dev [lindex $l 0] [lindex $l 1]
|
||||
incr devRun -1
|
||||
unset running($dev)
|
||||
}
|
||||
#-----------------------------------------------------------------------
|
||||
proc isDevRunning {dev} {
|
||||
upvar #0 running running
|
||||
return [info exists running($dev)]
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc cancelAll {} {
|
||||
upvar #0 running running devRun devRun devices devices
|
||||
upvar #0 sicsRestart sicsRestart
|
||||
if {$devRun > 0} {
|
||||
incr sicsRestart
|
||||
}
|
||||
set runlist [array names running]
|
||||
foreach dev $runlist {
|
||||
puts stdout "Live restart on device $dev"
|
||||
set l $running($dev)
|
||||
addToDevice unaccounted [lindex $l 0] [lindex $l 1]
|
||||
unset running($dev)
|
||||
}
|
||||
set devRun 0
|
||||
}
|
||||
#---------------------------------------------------------------------
|
||||
proc addRunDiff {dev stamp lastStamp} {
|
||||
upvar #0 running running devRun devRun
|
||||
|
||||
set diff [calcTimeDiff [lindex $lastStamp 0] \
|
||||
[lindex $lastStamp 1] \
|
||||
[lindex $stamp 0]\
|
||||
[lindex $stamp 1]]
|
||||
if {![info exists running($dev)] } {
|
||||
addToRunning $dev 0 0
|
||||
}
|
||||
set disSec [expr double([lindex $diff 0])/double($devRun)]
|
||||
set disNano [expr double([lindex $diff 1])/double($devRun)]
|
||||
set devlist [array names running]
|
||||
foreach d $devlist {
|
||||
addToRunning $d $disSec $disNano
|
||||
}
|
||||
}
|
||||
#---------------------------------------------------------------------
|
||||
proc clearAll {} {
|
||||
upvar #0 devRun devRun __lastStamp lastStamp __nobeamStamp nobeamStamp
|
||||
upvar #0 devices devices running running sicsRestart sicsRestart
|
||||
set devRun 0
|
||||
catch {unset lastStamp}
|
||||
catch {unset nobeamStamp}
|
||||
set l [array names devices]
|
||||
foreach d $l {
|
||||
unset devices($d)
|
||||
}
|
||||
set l [array names running]
|
||||
foreach d $l {
|
||||
unset running($d)
|
||||
}
|
||||
set devices(nobeam) 0
|
||||
set devices(unaccounted) 0
|
||||
set sicsRestart 0
|
||||
}
|
||||
#=======================================================================
|
||||
# This section contains the code with the main interpretation and
|
||||
# analysis
|
||||
#=======================================================================
|
||||
proc analyzeLine {line after} {
|
||||
upvar #0 devRun devRun __lastStamp lastStamp __nobeamStamp nobeamStamp
|
||||
set log [parseLogLine $line]
|
||||
set afterSec [clock scan $after]
|
||||
set op [getLogOp $log]
|
||||
set t [getLogSeconds $log]
|
||||
if {$t < $afterSec} {
|
||||
return
|
||||
}
|
||||
switch $op {
|
||||
START {
|
||||
set dev [getLogDevice $log]
|
||||
if {[string compare $dev SICS] == 0} {
|
||||
cancelAll
|
||||
return
|
||||
}
|
||||
if {$devRun > 0} {
|
||||
set stamp [getStamp $log]
|
||||
addRunDiff $dev $stamp $lastStamp
|
||||
set lastStamp $stamp
|
||||
} else {
|
||||
if {![isDevRunning $dev] } {
|
||||
addToRunning $dev 0 0
|
||||
set lastStamp [getStamp $log]
|
||||
}
|
||||
}
|
||||
}
|
||||
STOP {
|
||||
if {![info exists lastStamp]} {
|
||||
return
|
||||
}
|
||||
set dev [getLogDevice $log]
|
||||
if {[string compare $dev SICS] == 0} {
|
||||
cancelAll
|
||||
return
|
||||
}
|
||||
set stamp [getStamp $log]
|
||||
addRunDiff $dev $stamp $lastStamp
|
||||
if {[isDevRunning $dev] } {
|
||||
stopRunning $dev
|
||||
}
|
||||
if {$devRun == 0} {
|
||||
unset lastStamp
|
||||
}
|
||||
}
|
||||
NOBEAM {
|
||||
set nobeamStamp [getStamp $log]
|
||||
}
|
||||
CONTINUE {
|
||||
set stamp [getStamp $log]
|
||||
set diff [calcTimeDiff [lindex $nobeamStamp 0] \
|
||||
[lindex $nobeamStamp 1] \
|
||||
[lindex $stamp 0]\
|
||||
[lindex $stamp 1]]
|
||||
addToDevice nobeam [lindex $diff 0] [lindex $diff 1]
|
||||
unset nobeamStamp
|
||||
}
|
||||
}
|
||||
}
|
||||
#==========================================================================
|
||||
proc printResult {} {
|
||||
upvar #0 devices devices sicsRestart sicsRestart
|
||||
set l [array names devices]
|
||||
puts stdout "DEVICE SECONDS"
|
||||
foreach dev $l {
|
||||
puts stdout [format "%-20s %12.2f" $dev $devices($dev)]
|
||||
}
|
||||
puts stdout [format "%-20s %12.2f" "Live Restarts" $sicsRestart]
|
||||
}
|
||||
#=========================================================================
|
||||
proc analyzeFile {filename after} {
|
||||
set f [open $filename r]
|
||||
while {[gets $f line] >= 0} {
|
||||
set status [catch {analyzeLine $line $after} msg]
|
||||
if {$status != 0} {
|
||||
puts stdout "ERROR: error $msg processing $line"
|
||||
}
|
||||
}
|
||||
close $f
|
||||
}
|
||||
#=============== MAIN Program ===========================================
|
||||
proc main {} {
|
||||
global argv
|
||||
if {[llength $argv] < 2} {
|
||||
puts stdout "Usage:\n\tanalysedevexeclog filename after"
|
||||
puts stdout "\t with after being a date in format MM/DD/YYYY"
|
||||
exit 1
|
||||
}
|
||||
|
||||
analyzeFile [lindex $argv 0] [lindex $argv 1]
|
||||
|
||||
printResult
|
||||
}
|
||||
|
||||
main
|
||||
exit 0
|
||||
|
Reference in New Issue
Block a user