kuroko/modules/callgrind.krk
2021-03-25 09:54:23 +09:00

66 lines
2.7 KiB
Python

'''
@brief Tool to process VM trace reports and generate callgrind-formatted output.
'''
import kuroko
import fileio
def processFile(sourcePath: str, pid: int , cmd: str):
'''@brief Process @p sourcePath from process @p pid with command @p cmd as a VM trace file.'''
let funcs = {}
with fileio.open(sourcePath,'r') as f:
for line in f.readlines():
let callerFile, callerFunc, callerLine, calleeFile, calleeFunc, calleeLine, nsecs = line.split(' ')
nsecs = float(nsecs)
let data = funcs.get((callerFile,callerFunc),{})
let call = data.get((callerLine,calleeFile,calleeFunc,calleeLine),(0,0))
let out = (call[0] + 1, call[1] + nsecs)
data[callerLine,calleeFile,calleeFunc,calleeLine] = out
funcs[callerFile,callerFunc] = data
let called = funcs.get((calleeFile,calleeFunc),{})
let times = called.get(None,(1,0))
called[None] = (calleeLine, times[1] + nsecs)
funcs[calleeFile,calleeFunc] = called
with fileio.open(f'callgrind.out.{pid}','w') as out:
out.write('# callgrind format\n')
out.write('creator: Kuroko\n')
out.write('positions: line\n')
out.write('events: nanoseconds\n')
out.write(f'cmd: {cmd}\n\n')
def defloat(f):
let s = int(f)
let n = str(int(f * 1000000000))
if len(n) > 9: n = n[-9:]
let o = (str(s) + '0' * (9 - len(n)) + n).lstrip('0')
return o if o else '0'
def cleanfunc(func):
for s in ['<module>','<listcomp>','<setcomp>','<dictcomp>','<lambda>']:
func = func.replace(s,'['+s[1:-1]+']')
return func.replace('@','<') + '>'
for key, value in funcs.items():
let sFile, sFunc = key
out.write(f'fl={sFile}\n')
out.write(f'fn={cleanfunc(sFunc)}\n')
if not sFunc.startswith('(root)'):
let startLine, totalNsecs = value[None]
for k, v in value.items():
if not k: continue
let sourceLine, file, func, destLine = k
let count, nsecs = v
totalNsecs -= nsecs
out.write(f'{startLine} {defloat(totalNsecs)}\n')
for k, v in value.items():
if not k: continue
let sourceLine, file, func, destLine = k
let count, totalNsecs = v
if file != sFile: out.write(f'cfi={file}\n')
out.write(f'cfn={cleanfunc(func)}\n')
out.write(f'calls={count} {destLine}\n')
out.write(f'{sourceLine} {defloat(totalNsecs)}\n')
out.write('\n')