From 9246ed61f03869db58743481157879db5a23d89c Mon Sep 17 00:00:00 2001 From: iipeace Date: Sun, 5 Jan 2025 23:51:41 +0900 Subject: [PATCH] Debugger: Add PMU stats Signed-off-by: iipeace --- guider/guider.py | 93 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 28 deletions(-) diff --git a/guider/guider.py b/guider/guider.py index f507e16a..ab823cd9 100755 --- a/guider/guider.py +++ b/guider/guider.py @@ -7,7 +7,7 @@ __credits__ = "Peace Lee" __license__ = "GPLv2" __version__ = "3.9.8" -__revision__ = "250104" +__revision__ = "250105" __maintainer__ = "Peace Lee" __email__ = "iipeace5@gmail.com" __repository__ = "https://github.com/iipeace/guider" @@ -39964,6 +39964,9 @@ def printHelp(force=False, isExit=True): - Monitor CPU usage on whole system # {0:1} {1:1} {2:1} -e c + - Print PMU stats + # {0:1} {1:1} {2:1} -e P + - Draw timeline segments for function calls # {0:1} {1:1} {2:1} -q TIMELINE, TIMEUNIT:ms, INTERCALL, DURATION:10 # {0:1} {1:1} {2:1} -q TIMELINE, TIMEUNIT:us, INTERCALL, DURATION:100 -H -a @@ -42666,7 +42669,7 @@ def _getDesc(s, t=0): helpStr += """ Options: -e enable options - [ p:pipe | e:encode ] + [ D:DWARF | p:pipe | P:perf | e:encode ] -d disable options [ C:clone | e:encode | E:exec | g:general | O:color ] -u run in the background @@ -42726,7 +42729,7 @@ def _getDesc(s, t=0): helpStr += """ Options: -e enable options - [ p:pipe | e:encode ] + [ D:DWARF | p:pipe | P:perf | e:encode ] -d disable options [ C:clone | e:encode | E:exec | g:general | O:color ] -u run in the background @@ -42843,7 +42846,7 @@ def _getDesc(s, t=0): helpStr += """ Options: -e enable options - [ p:pipe | D:DWARF | e:encode ] + [ D:DWARF | p:pipe | P:perf | e:encode ] -d disable options [ C:clone | e:encode | d:demangle | D:DWARF | E:exec | g:general ] -u run in the background @@ -42910,7 +42913,7 @@ def _getDesc(s, t=0): helpStr += """ Options: -e enable options - [ p:pipe | D:DWARF | e:encode ] + [ D:DWARF | p:pipe | P:perf | e:encode ] -d disable options [ C:clone | d:demangle | D:DWARF | e:encode | E:exec | g:general ] -u run in the background @@ -42979,7 +42982,7 @@ def _getDesc(s, t=0): helpStr += """ Options: -e enable options - [ p:pipe | D:DWARF | e:encode ] + [ D:DWARF | p:pipe | P:perf | e:encode ] -d disable options [ C:clone | d:demangle | D:DWARF | e:encode | E:exec | g:general ] -u run in the background @@ -43247,7 +43250,7 @@ def _getDesc(s, t=0): helpStr += """ Options: -e enable options - [ p:pipe | e:encode ] + [ p:pipe | P:perf | e:encode ] -d disable options [ C:clone | e:encode | E:exec | g:general ] -u run in the background @@ -49688,8 +49691,8 @@ def getPerfString(value): if not value: return perfbuf - convColor = UtilMgr.convColor convSize = UtilMgr.convSize2Unit + convColor = lambda x: UtilMgr.convColor(x, "YELLOW") inst = cpucycle = -1 cacheref = cachemiss = cachemissrate = -1 @@ -49700,17 +49703,19 @@ def getPerfString(value): cpucycle = value["PERF_COUNT_HW_CPU_CYCLES"] perfbuf = "%sCycle: %s / " % ( perfbuf, - convColor(convSize(cpucycle), "YELLOW"), + convColor(convSize(cpucycle)) if cpucycle else 0, ) + inst = value["PERF_COUNT_HW_INSTRUCTIONS"] perfbuf = "%sInst: %s / " % ( perfbuf, - convColor(convSize(inst), "YELLOW"), + convColor(convSize(inst)) if inst else 0, ) + ipc = inst / float(cpucycle) perfbuf = "%sIPC: %s / " % ( perfbuf, - convColor("%.2f" % ipc, "YELLOW"), + convColor("%.2f" % ipc) if ipc else 0, ) except SystemExit: sys.exit(0) @@ -49725,7 +49730,7 @@ def getPerfString(value): perfbuf = "%sCacheMiss : %s(%s) / " % ( perfbuf, convSize(cachemiss), - convColor("%s%%" % cachemissrate, "YELLOW"), + convColor("%s%%" % cachemissrate), ) except SystemExit: sys.exit(0) @@ -49740,7 +49745,7 @@ def getPerfString(value): perfbuf = "%sBrcMiss: %s(%s) / " % ( perfbuf, convSize(branchmiss), - convColor("%s%%" % branchmissrate, "YELLOW"), + convColor("%s%%" % branchmissrate), ) except SystemExit: sys.exit(0) @@ -49749,9 +49754,10 @@ def getPerfString(value): # CPU stats # try: + clock = value["PERF_COUNT_SW_CPU_CLOCK"] / 1000000000.0 perfbuf = "%sClk: %s / " % ( perfbuf, - convSize(value["PERF_COUNT_SW_CPU_CLOCK"]), + convColor(UtilMgr.convTime2Unit(clock)) if clock else 0, ) except SystemExit: sys.exit(0) @@ -49764,8 +49770,8 @@ def getPerfString(value): faultmaj = value["PERF_COUNT_SW_PAGE_FAULTS_MAJ"] perfbuf = "%sMinFlt: %s / MajFlt: %s / " % ( perfbuf, - format(faultmin, ","), - format(faultmaj, ","), + convColor(format(faultmin, ",")) if faultmin else 0, + convColor(format(faultmaj, ",")) if faultmaj else 0, ) except SystemExit: sys.exit(0) @@ -49773,8 +49779,7 @@ def getPerfString(value): pass try: - if perfbuf: - perfbuf = "%s" % perfbuf[: perfbuf.rfind(" /")] + perfbuf = perfbuf[: perfbuf.rfind(" /")] except SystemExit: sys.exit(0) except: @@ -56746,6 +56751,11 @@ def parseAnalOption(option=None): SysMgr.checkRootPerm() SysMgr.delayEnable = True + if "P" in options: + SysMgr.perfEnable = True + if SysMgr.findOption("g"): + SysMgr.perfGroupEnable = True + # below options only for top mode # if not SysMgr.isTopMode(): continue @@ -56759,11 +56769,6 @@ def parseAnalOption(option=None): if "p" in options: SysMgr.pipeEnable = True - if "P" in options: - SysMgr.perfEnable = True - if SysMgr.findOption("g"): - SysMgr.perfGroupEnable = True - if "i" in options: SysMgr.irqEnable = True @@ -101519,7 +101524,7 @@ def _updateNeedStop(): ret = SysMgr.addPrint( ( "[Top %s Info] [Time: %.3f] [Inter: %.3f] [Sample: %s] " - "%s[SYS: %s/%s] [%s(%s)%s: %s/%s] [%s(%s): %s/%s]%s \n%s\n" + "%s[SYS: %s/%s] [%s(%s)%s: %s/%s] [%s(%s): %s/%s]%s \n" ) % ( ctype, @@ -101539,21 +101544,30 @@ def _updateNeedStop(): mcpuStr, mrssStr, sampleStr, - twoLine, ), - newline=2, ) if not ret: # flush print buffer # _finishPrint(self, needStop, term) return + # print PMU stats # + if self.perfFds: + perfData = SysMgr.collectProcPerfData(self.perfFds) + perfRes = SysMgr.getPerfString(perfData) + if perfRes: + ret = SysMgr.addPrint("[PMU] " + perfRes + "\n") + if not ret: + # flush print buffer # + _finishPrint(self, needStop, term) + return + # print menu # ret = SysMgr.addPrint( - "{0:^7} | {1:<144}\n{2:<1}\n".format( + "{2:1}\n{0:^7} | {1:<144}\n{2:<1}\n".format( "Usage", "Function %s" % addInfo, twoLine ), - newline=2, + newline=3, ) if not ret: # flush print buffer # @@ -107957,6 +107971,12 @@ def initValues(self, fork=True): else True ) + # PMU # + self.perfFds = {} + if SysMgr.perfEnable: + SysMgr.initSystemPerfEvents() + self.perfFds = SysMgr.initProcPerfEvents(self.pid) + # init fd # if fork: self.memFd = None @@ -109089,8 +109109,21 @@ def _printSystemStat(): # save system info # SysMgr.saveSysStats(True) + # get PMU stats # + perfString = "" + try: + if not instance.perfFds: + raise Exception() + perfData = SysMgr.collectProcPerfData(instance.perfFds) + perfRes = SysMgr.getPerfString(perfData) + if perfRes: + perfString = "[PMU] " + perfRes + except: + pass + # check realtime mode # if not SysMgr.outPath or SysMgr.jsonEnable: + SysMgr.printPipe(perfString) return elif ( not instance.callList and not "FORCESUMMARY" in SysMgr.environList @@ -109100,6 +109133,7 @@ def _printSystemStat(): % (instance.comm, instance.pid), True, ) + SysMgr.printPipe(perfString) return # summarize samples after last tick # @@ -109234,6 +109268,7 @@ def _printSystemStat(): if needStop: instance.stop(check=True) + SysMgr.printPipe(perfString) return except: pass @@ -109480,6 +109515,8 @@ def _printSystemStat(): except: rfreqStr = "" + SysMgr.printPipe(perfString) + # print title # titleStr = ( "\n[%s %s Summary] [Elapsed: %.3f]%s%s%s%s "