From 3543749a34e30f56f00d27901fb90a81a4f04bd4 Mon Sep 17 00:00:00 2001 From: iipeace Date: Tue, 24 Sep 2024 23:21:33 +0900 Subject: [PATCH] tptop: Add interval stats Signed-off-by: iipeace --- guider/guider.py | 128 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 23 deletions(-) diff --git a/guider/guider.py b/guider/guider.py index a9884ce3..52c48248 100755 --- a/guider/guider.py +++ b/guider/guider.py @@ -7,7 +7,7 @@ __credits__ = "Peace Lee" __license__ = "GPLv2" __version__ = "3.9.8" -__revision__ = "240923" +__revision__ = "240924" __maintainer__ = "Peace Lee" __email__ = "iipeace5@gmail.com" __repository__ = "https://github.com/iipeace/guider" @@ -25122,20 +25122,55 @@ def _updateBinderStat(binderStat, ctask, code): def parseTraceData(data): LogMgr.traceStat["cnt"] = LogMgr.traceStat.get("cnt", 0) + 1 + # save count # func = data.get("func") if not func in LogMgr.traceStat: LogMgr.traceStat[func] = {"cnt": 0} - LogMgr.traceStat[func]["cnt"] += 1 + funcStat = LogMgr.traceStat[func] + funcStat["cnt"] += 1 + + # save stat # + if "PRINTSTAT" in SysMgr.environList: + ltime = float(data.get("time", 0)) + last = funcStat.get("last", 0) + if last: + diff = ltime - last + if diff > 0: + funcStat["min"] = min(funcStat["min"], diff) + funcStat["max"] = max(funcStat["max"], diff) + funcStat["total"] += diff + else: + funcStat["min"] = SysMgr.maxSize + funcStat["total"] = funcStat["max"] = 0 + funcStat["last"] = ltime + else: + ltime = 0 if "ONLYEVENT" in SysMgr.environList: return + # save task count # tid = data.get("tgid" if SysMgr.processEnable else "thread") if tid[0] == "-": tid = data.get("thread") - if not tid in LogMgr.traceStat[func]: - LogMgr.traceStat[func][tid] = {"cnt": 0, "comm": data.get("comm")} - LogMgr.traceStat[func][tid]["cnt"] += 1 + if not tid in funcStat: + funcStat[tid] = {"cnt": 0, "comm": data.get("comm")} + taskStat = funcStat[tid] + taskStat["cnt"] += 1 + + # save task stat # + if "PRINTSTAT" in SysMgr.environList: + last = taskStat.get("last", 0) + if last: + diff = ltime - last + if diff > 0: + taskStat["min"] = min(taskStat["min"], diff) + taskStat["max"] = max(taskStat["max"], diff) + taskStat["total"] += diff + else: + taskStat["min"] = SysMgr.maxSize + taskStat["total"] = taskStat["max"] = 0 + taskStat["last"] = ltime @staticmethod def atraceHandler(signum, frame): @@ -25706,15 +25741,34 @@ def traceHandler(signum, frame): ) SysMgr.addPrint( - "{2:1}\n{0:^65} | {1:^32} |\n{2:1}\n".format( - "EVENT", "TASK", twoLine - ), + ( + "{6:1}\n{0:^65} | {1:^32} | {2:^9} | {3:^9} | " + "{4:^9} | {5:^13} |\n{6:1}\n" + ).format("EVENT", "TASK", "AVG", "MIN", "MAX", "TOTAL", twoLine), newline=2, force=force, ) taskFilter = SysMgr.environList.get("TASKFILTER", []) + def _getStats(statList, totalCnt, indent=True): + statStr = "" + total = statList.get("total", 0) + if total > 0: + statStr += ( + "{0:>{idlen}} {1:>9.6f} {2:>9.6f} " + "{3:>9.6f} {4:>13.6f}" + ).format( + " ", + total / float(totalCnt) if totalCnt else 0, + statList.get("min"), + statList.get("max"), + total, + idlen=36 if indent else 1, + ) + statStr += "\n" + return statStr + # traverse trace table # logCnt = 0 totalCnt = float(LogMgr.traceStat.get("cnt", 0)) @@ -25731,18 +25785,19 @@ def traceHandler(signum, frame): eventCnt = tasks.get("cnt") eventPer = (eventCnt / totalCnt) * 100 - eventStr = "{0:>49} {1:>8}({2:5.1f}%)\n".format( + eventStr = "{0:>49} {1:>8}({2:5.1f}%)".format( event, convNum(eventCnt), eventPer ) + eventStr += _getStats(tasks, eventCnt, True) SysMgr.addPrint(eventStr, force=force) logCnt += 1 for task, items in sorted( tasks.items(), - key=lambda x: x[1]["cnt"] if x[0] != "cnt" else 0, + key=lambda x: x[1]["cnt"] if x[0][0].isdigit() else 0, reverse=True, ): - if task == "cnt": + if not task.isdigit(): continue # check exit condition # @@ -25769,9 +25824,10 @@ def traceHandler(signum, frame): taskInfo = "%s(%s)" % (comm, task) taskCnt = items["cnt"] taskPer = (taskCnt / float(eventCnt)) * 100 - taskStr = "{0:34}{1:>50} {2:>8}({3:5.1f}%)\n".format( + taskStr = "{0:34}{1:>50} {2:>8}({3:5.1f}%)".format( " ", taskInfo, convNum(taskCnt), taskPer ) + taskStr += _getStats(items, taskCnt, False) SysMgr.addPrint(taskStr, force=force) if logCnt == 0: @@ -38644,6 +38700,9 @@ def printHelp(force=False, isExit=True): - {2:1} except for load plots including CPU and I/O usage # {0:1} {1:1} {4:1} -q NOLOADPLOT + - {2:1} including core usage + # {0:1} {1:1} {4:1} -q COREPLOT + - {2:1} except for PSI plots # {0:1} {1:1} {4:1} -q NOPSIPLOT @@ -40760,6 +40819,7 @@ def _getDesc(s, t=0): Examples: - {2:1} # {0:1} {1:1} {3:1} + # {0:1} {1:1} syscalls - {2:1} only having specific words # {0:1} {1:1} {3:1} -g test, kworker @@ -40767,6 +40827,13 @@ def _getDesc(s, t=0): - {2:1} only for specific tasks # {0:1} {1:1} {3:1} -q TASKFILTER:"test*" + - {2:1} with interval stats + # {0:1} {1:1} {3:1} -q PRINTSTAT + + - {2:1} after applying filters + # {0:1} {1:1} {3:1} -q TPFILTER:"sched:common_pid==895" + # {0:1} {1:1} {3:1} -q TPFILTER:"sched/sched_switch:prev_comm==\\"yes\\"" + - {2:1} with control for specific trace points # {0:1} {1:1} {3:1} "irq/softirq*, sched" # {0:1} {1:1} {3:1} "sched/sched_blocked_reason" @@ -43593,6 +43660,7 @@ def _getDesc(s, t=0): - {2:1} after applying filters # {0:1} {1:1} "*" -q TPFILTER:"sched:common_pid==895" + # {0:1} {1:1} "*" -q TPFILTER:"sched/sched_switch:prev_comm==\\"yes\\"" - Print tracepoint list # {0:1} {1:1} -l @@ -120310,8 +120378,9 @@ def getStatsFile( # Core # elif context == "Core": if slen == 3: - gname = sline[0].strip() - intervalList = sline[2] + if not sline[0].startswith("Core"): + gname = sline[0].strip() + intervalList = sline[2] elif slen == 2: if intervalList: intervalList += sline[1] @@ -123885,6 +123954,18 @@ def _drawCpu(graphStats, xtype, pos, size, delay=False): (cpuUsage, "red", "CPU(%s)" % conv(maxCore), bold, ""), ] + # add core stat # + if "COREPLOT" in SysMgr.environList: + coreUsage = graphStats["%scoreUsage" % fname] + for corenum, ulist in sorted( + coreUsage.items(), key=lambda x: long(x[0]) + ): + ulist = list(map(long, ulist.split())) + cname = "Core/%s" % corenum + coreStatList.append( + (ulist, None, cname, bold, cname + " | ") + ) + # process PSI stats # psiStats = ( {} @@ -132324,10 +132405,11 @@ def parseProcLine(index, procLine): # split stats # tokens = procLine.split("|") + lenToken = len(tokens) # total # if "total" not in procIntData and tokens[0].startswith("Total"): - if len(tokens) < 2: + if lenToken < 2: return # parse CPU & BLOCK stat # @@ -132468,7 +132550,7 @@ def parseProcLine(index, procLine): return # PSI # - elif len(tokens) == 1 and tokens[0].startswith(" "): + elif lenToken == 1 and tokens[0].startswith(" "): # parse PSI stat # m = re.match( ( @@ -132489,7 +132571,7 @@ def parseProcLine(index, procLine): TA.procTempData["psi"] = psiStats # GPU # - elif len(tokens) == 5: + elif lenToken == 5: m = re.match( r"\s*(?P.+)\s*\(\s*(?P[0-9]+)\s*%\)", tokens[0] ) @@ -132525,7 +132607,7 @@ def parseProcLine(index, procLine): return # storage # - elif len(tokens) == 12 and tokens[0][0] == "/": + elif lenToken == 12 and tokens[0][0] == "/": procIntData["total"].setdefault("storage", {}) TA.procTotData["total"].setdefault("storage", {}) @@ -132593,7 +132675,7 @@ def parseProcLine(index, procLine): return # network # - elif len(tokens) == 13 and not tokens[0].startswith("Total"): + elif lenToken == 13 and not tokens[0].startswith("Total"): # check condition # if tokens[0].strip() in ("ID", "Dev"): return @@ -132631,9 +132713,9 @@ def parseProcLine(index, procLine): return # cgroup # - elif len(tokens) == 10 and "/" in tokens[8]: + elif lenToken == 10 and "/" in tokens[8]: tokens = UtilMgr.cleanItem(tokens, False) - if len(tokens) != 9: + if lenToken != 9: return try: @@ -132714,7 +132796,7 @@ def parseProcLine(index, procLine): return # core # - elif len(tokens) == 6 and tokens[0].startswith("Core/"): + elif lenToken in (6, 7) and tokens[0].startswith("Core/"): m = re.findall( r"Core/\s*(?P\d+)\|\s*(?P\d+)\s*%", procLine ) @@ -132736,7 +132818,7 @@ def parseProcLine(index, procLine): procIntData["total"]["core"][core] = usage # WARN: each tab's the number of tokens # - # task(10), GPU(5), storage(12), network(13), cgroup(10), core(6) + # task(10), GPU(5), storage(12), network(13), cgroup(10), core(6/7) # check return condition # if "ONLYTOTAL" in SysMgr.environList: