Skip to content

Commit

Permalink
mdtop: Add mdtop command
Browse files Browse the repository at this point in the history
Signed-off-by: iipeace <[email protected]>
  • Loading branch information
iipeace committed Oct 30, 2024
1 parent 0d93631 commit 9981b61
Showing 1 changed file with 103 additions and 21 deletions.
124 changes: 103 additions & 21 deletions guider/guider.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
__credits__ = "Peace Lee"
__license__ = "GPLv2"
__version__ = "3.9.8"
__revision__ = "241029"
__revision__ = "241030"
__maintainer__ = "Peace Lee"
__email__ = "[email protected]"
__repository__ = "https://github.com/iipeace/guider"
Expand Down Expand Up @@ -30497,6 +30497,16 @@ def execTopCmd():
LogMgr.printTrace(False)
sys.exit(0)

# memory dump #
elif SysMgr.checkMode("mdtop"):
if not SysMgr.filterGroup:
SysMgr.printErr("no input for target info")
sys.exit(0)

SysMgr.addEnvironVar("MEMTOP")
SysMgr.doHeapProfRec()
sys.exit(0)

# binder #
elif SysMgr.checkMode("bdtop"):
SysMgr.addEnvironVar("FLUSH")
Expand Down Expand Up @@ -38136,6 +38146,7 @@ def getCmdList():
"irqtop": ("IRQ", "Linux"),
"kftop": ("Function", "Linux"),
"ktop": ("Function", "Linux"),
"mdtop": ("MemDump", "Linux"),
"mtop": ("Memory", "Linux"),
"ntop": ("Network", "Linux/MacOS/Windows"),
"ptop": ("PMU", "Linux"),
Expand Down Expand Up @@ -41114,6 +41125,27 @@ def _getDesc(s, t=0):

helpStr += topCommonStr + examStr

# memory dump top #
elif SysMgr.checkMode("mdtop"):
helpStr = _getDesc(
"Monitor memory details for a process using dumpsys meminfo",
)

examStr = """
Examples:
- {2:1}
# {0:1} {1:1} -g system_server
# {0:1} {1:1} -g com.android.car -q APP

See the top COMMAND help for more examples.
""".format(
cmd,
mode,
"Monitor memory details for a process using dumpsys meminfo",
)

helpStr += topSubStr + topCommonStr + examStr

# binder top #
elif SysMgr.checkMode("bdtop"):
helpStr = _getDesc(
Expand Down Expand Up @@ -56602,6 +56634,7 @@ def isTopMode():
"irqtop",
"kftop",
"ktop",
"mdtop",
"mtop",
"ntop",
"ptop",
Expand Down Expand Up @@ -58848,6 +58881,7 @@ def parseMemDump(data):
"appSummary": {},
"objects": {},
"sql": {},
"databases": [],
}

# define regex patterns for each section and their items #
Expand All @@ -58870,6 +58904,9 @@ def parseMemDump(data):
"sql": re.compile(
r"(MEMORY_USED|PAGECACHE_OVERFLOW|MALLOC_SIZE):\s+(\d+)"
),
"databases": re.compile(
r"\s*(\d+)\s+(\d+)\s*(\d*)\s*(\d+)/(\d+)/(\d+)\s+(.*)"
),
}

# parse uptime #
Expand Down Expand Up @@ -58908,6 +58945,25 @@ def parseMemDump(data):
for match in patterns["sql"].finditer(data):
result["sql"][match.group(1)] = int(match.group(2))

# parse databases #
for match in patterns["databases"].finditer(data):
pgsz, dbsz, lookaside, cache_1, cache_2, cache_3, dbname = (
match.groups()
)
result["databases"].append(
{
"pgsz": int(pgsz),
"dbsz": int(dbsz),
"lookaside": int(lookaside) if lookaside else None,
"cache": {
"cache_1": int(cache_1),
"cache_2": int(cache_2),
"cache_3": int(cache_3),
},
"dbname": dbname.strip(),
}
)

return result

@staticmethod
Expand Down Expand Up @@ -59968,7 +60024,7 @@ def convHeapProfSample(path, scripts=[], statusDict={}):
return scripts

# define lists #
buf = ""
buf = []
maps = {}
paths = {}
stacks = {}
Expand All @@ -59992,6 +60048,7 @@ def convHeapProfSample(path, scripts=[], statusDict={}):
totalCnt = 0
totalSize = 0
totalLength = len(scripts) if isinstance(scripts, list) else 0
printPkgList = "PRINTPKGLIST" in SysMgr.environList

def _printErr(err, reason=False):
SysMgr.printErr(err, reason=reason)
Expand All @@ -60011,18 +60068,19 @@ def _getLine(scripts):
try:
if isinstance(scripts, list):
yield idx, scripts[idx]
idx += 1
else:
line = scripts.readline()
if line == "":
raise Exception()
elif isinstance(line, bytes):
line = line.decode()
yield idx, line.rstrip("\n")
idx += 1
except SystemExit:
sys.exit(0)
except:
yield idx, None
idx += 1

# parse lines #
for idx, l in _getLine(scripts):
Expand All @@ -60039,10 +60097,9 @@ def _getLine(scripts):
l = l.rstrip()

if l.startswith("packet {"):
buf = "{"
buf = ["{"]
elif l.startswith("}"):
buf = buf.rstrip(",") + "}"
encoded = buf.replace("\\", "\\\\")
encoded = ("".join(buf).rstrip(",") + "}").replace("\\", "\\\\")
json = UtilMgr.convStr2Dict(encoded, True, True)

# save data #
Expand Down Expand Up @@ -60071,12 +60128,13 @@ def _getLine(scripts):
packets[s] = v

# reset buffer #
buf = ""
buf = []
elif l.endswith("{"):
l = '"%s": {' % l.rsplit("{", 1)[0].strip()
buf += l
buf.append(l)
elif l.endswith("}"):
buf = buf.rstrip(",") + "},"
buf[-1] = buf[-1].rstrip(",")
buf.append("},")
else:
ll = l.split(":", 1)
if len(ll) == 1:
Expand All @@ -60086,7 +60144,7 @@ def _getLine(scripts):
ll[0].strip(),
":".join(ll[1:]).strip('" ').replace('"', "'"),
)
buf += l
buf.append(l)
except SystemExit:
sys.exit(0)
except:
Expand Down Expand Up @@ -60171,11 +60229,13 @@ def _saveSysInfo(pstr):
pkglist.append(pinfo)

# print package info #
if UtilMgr.isValidStr(pname, targetPkgs):
if not printPkgList and targetPkgs and UtilMgr.isValidStr(
pname, targetPkgs
):
SysMgr.printInfo(pkglist[-1], color=False)

# print package list #
if pkglist and "PRINTPKGLIST" in SysMgr.environList:
if pkglist and printPkgList:
# print package info #
_printInfo("\n".join(pkglist).rstrip(), color=False)

Expand Down Expand Up @@ -60242,7 +60302,7 @@ def _saveSysInfo(pstr):
_saveSysInfo(pstr)

# save callstack info #
for s in samples:
for s in samples if isinstance(samples, list) else []:
cid = s.pop("callstack_id")
if not cid:
continue
Expand All @@ -60254,14 +60314,27 @@ def _saveSysInfo(pstr):
for n, v in s.items():
stacks[cid][n] = long(stacks[cid].get(n, 0)) + long(v)

# process internedData for callstacks #
# get internedData for callstacks #
internedData = packets.get("interned_data")
if not internedData:
_printErr("no profiled intenred data")
return -1
for x in (
[internedData] if isinstance(internedData, dict) else internedData
):

# convert internedData #
internedList = []
if isinstance(internedData, dict):
internedList.append(internedData)
elif isinstance(internedData, list):
for x in internedData:
if isinstance(x, list):
internedList += x
else:
internedList.append(x)
else:
SysMgr.printErr("failed to recognize interned data")

# process internedData for callstacks #
for x in internedList:
# check type #
if not isinstance(x, dict):
continue
Expand Down Expand Up @@ -60319,14 +60392,23 @@ def _saveSysInfo(pstr):
for cid, stats in stacks.items():
stack = []
for fid in reversed(callstacks[cid] if cid in callstacks else []):
# check fid #
if not fid in frames:
SysMgr.printWarn("failed to get frame ID '%s'" % fid, always=True)
stack.append([0, "??", "??"])
continue

# make full path #
fpath = mapCache.get(fid)
if not fpath:
mid = frames[fid]["mapping_id"]
midxs = maps[mid]["path_string_ids"]
if not isinstance(midxs, list):
midxs = [midxs]
fpath = "/" + "/".join([paths[m] for m in midxs])
midxs = maps[mid].get("path_string_ids", -1)
if midxs == -1:
fpath = "??"
else:
if not isinstance(midxs, list):
midxs = [midxs]
fpath = "/" + "/".join([paths[m] for m in midxs])
mapCache[fid] = fpath

# make function #
Expand Down

0 comments on commit 9981b61

Please sign in to comment.