-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: iipeace <[email protected]>
- Loading branch information
Showing
1 changed file
with
158 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
__credits__ = "Peace Lee" | ||
__license__ = "GPLv2" | ||
__version__ = "3.9.8" | ||
__revision__ = "240720" | ||
__revision__ = "240722" | ||
__maintainer__ = "Peace Lee" | ||
__email__ = "[email protected]" | ||
__repository__ = "https://github.com/iipeace/guider" | ||
|
@@ -6012,7 +6012,7 @@ class ConfigMgr(object): | |
"PTRACE_EVENT_STOP": 128, | ||
} | ||
|
||
# ptrace o types # | ||
# ptrace trace types # | ||
PTRACE_O_TYPE = { | ||
"PTRACE_O_TRACESYSGOOD": 1, | ||
"PTRACE_O_TRACEFORK": 1 << PTRACE_EVENT_TYPE["PTRACE_EVENT_FORK"], | ||
|
@@ -9585,9 +9585,26 @@ def convUlong2Long(retval): | |
return retval | ||
|
||
@staticmethod | ||
def convStr2Dict(strObj, verb=False): | ||
def convStr2Dict(strObj, verb=False, duplist=False): | ||
try: | ||
return SysMgr.getPkg("json").loads(strObj) | ||
# convert duplicated keys to list # | ||
if duplist: | ||
|
||
def _parser(pairs): | ||
defaultdict = SysMgr.getPkg("collections").defaultdict | ||
d = defaultdict(list) | ||
for key, value in pairs: | ||
d[key].append(value) | ||
return { | ||
key: value[0] if len(value) == 1 else value | ||
for key, value in d.items() | ||
} | ||
|
||
return SysMgr.getPkg("json").loads( | ||
strObj, object_pairs_hook=_parser | ||
) | ||
else: | ||
return SysMgr.getPkg("json").loads(strObj) | ||
except SystemExit: | ||
sys.exit(0) | ||
except: | ||
|
@@ -41392,6 +41409,9 @@ def _getDesc(s, t=0): | |
# {0:1} {1:1} -q PERFETTO:/data/perfetto | ||
# {0:1} {1:1} -q TRACECONV:/data/traceconv | ||
|
||
- {2:1} for whole system with meta info | ||
# {0:1} {1:1} -v | ||
|
||
- {2:1} for specific processes | ||
# {0:1} {1:1} -g a.out, surfaceflinger | ||
|
||
|
@@ -41407,7 +41427,9 @@ def _getDesc(s, t=0): | |
- {2:1} for specific processes with 1000 bytes interval sampling | ||
# {0:1} {1:1} -g a.out, surfaceflinger -T 1000 | ||
|
||
- {2:1} after setting debuggable attribute | ||
- {2:1} after changing debuggable attribute | ||
# {0:1} {1:1} -q SETDEBUG | ||
# {0:1} {1:1} -q CLEARDEBUG | ||
# {0:1} {1:1} -q SETDEBUG:com.android.phone | ||
|
||
- {2:1} for specific processes with adding options | ||
|
@@ -41473,6 +41495,9 @@ def _getDesc(s, t=0): | |
# {0:1} {1:1} | ||
# {0:1} {1:1} -q SIMPLEPERF:/data/simpleperf | ||
|
||
- {2:1} for whole system with meta info | ||
# {0:1} {1:1} -v | ||
|
||
- {2:1} for specific processes | ||
# {0:1} {1:1} -g a.out, surfaceflinger | ||
|
||
|
@@ -56592,13 +56617,15 @@ def doHeapProfRec(appName=None): | |
if exe: | ||
cmdstr = "command: %s" % " ".join(exe) | ||
targetstr = 'process_cmdline: "%s"' % exe | ||
target = exe | ||
elif "APP" in SysMgr.environList: | ||
apps = ",".join(SysMgr.filterGroup) | ||
if not apps: | ||
SysMgr.printErr("failed to get app list") | ||
return -1 | ||
cmdstr = "app: %s" % apps | ||
targetstr = 'process_cmdline: "%s"' % apps | ||
target = apps | ||
elif SysMgr.filterGroup: | ||
pids = [] | ||
for g in SysMgr.filterGroup: | ||
|
@@ -56612,9 +56639,11 @@ def doHeapProfRec(appName=None): | |
SysMgr.getCommList(pids), | ||
) | ||
targetstr = 'process_cmdline: "%s"' % ",".join(pids) | ||
target = pids[0] | ||
else: | ||
cmdstr = ": SYSTEM" | ||
targetstr = "all_heaps: true" | ||
target = None | ||
|
||
# print command # | ||
SysMgr.printInfo("set target " + cmdstr) | ||
|
@@ -56655,12 +56684,18 @@ def doHeapProfRec(appName=None): | |
if SysMgr.warnEnable: | ||
SysMgr.printWarn(config) | ||
|
||
# check and set debuggable attribute # | ||
# change debuggable attribute # | ||
# WARN: target app will be restarted | ||
for a in SysMgr.environList.get("SETDEBUG", []): | ||
SysMgr.executeCommand( | ||
["am set-debug-app -w --persistent " + a] | ||
) | ||
for t, cmd in ( | ||
("SETDEBUG", "set-debug-app"), | ||
("CLEARDEBUG", "clear-debug-app"), | ||
): | ||
for a in SysMgr.environList.get(t, []): | ||
if a == "SET": | ||
a = target | ||
SysMgr.executeCommand( | ||
["am %s -w --persistent %s" % (cmd, a)] | ||
) | ||
|
||
# make default record command # | ||
cmd = [binPath, "--txt", "-c", "-", "-o", outPath, "-d"] | ||
|
@@ -57078,6 +57113,18 @@ def convHeapProfSample(path, scripts=[]): | |
if scripts == -1: | ||
return scripts | ||
|
||
# define lists # | ||
buf = "" | ||
stacks = {} | ||
packets = {} | ||
sourceList = [ | ||
"trace_config", | ||
"system_info", | ||
"packages_list", | ||
"profile_packet", | ||
"interned_data", | ||
] | ||
|
||
# parse lines # | ||
totalCnt = 0 | ||
totalSize = 0 | ||
|
@@ -57086,6 +57133,46 @@ def convHeapProfSample(path, scripts=[]): | |
try: | ||
UtilMgr.printProgress(idx, totalLength) | ||
totalSize += len(l) | ||
|
||
if l.startswith("packet {"): | ||
buf = "{" | ||
elif l.startswith("}"): | ||
buf = buf.rstrip(",") + "}" | ||
encoded = buf.replace("\\", "\\\\") | ||
json = UtilMgr.convStr2Dict(encoded, True, True) | ||
|
||
# save data # | ||
if json: | ||
for s in sourceList: | ||
v = json.get(s) | ||
if not v: | ||
continue | ||
|
||
# duplicated # | ||
if s in packets: | ||
if not isinstance(type(packets[s]), list): | ||
packets[s] = [packets[s]] | ||
packets[s].append(v) | ||
else: | ||
packets[s] = v | ||
|
||
# reset buffer # | ||
buf = "" | ||
elif l.endswith("{\n"): | ||
l = '"%s": {' % l.rsplit("{", 1)[0].strip() | ||
buf += l | ||
elif l.endswith("}\n"): | ||
buf = buf.rstrip(",") + "}," | ||
else: | ||
ll = l.rstrip().split(":", 1) | ||
if len(ll) == 1: | ||
l = ll[0] | ||
else: | ||
l = '"%s": "%s",' % ( | ||
ll[0].strip(), | ||
":".join(ll[1:]).strip('" ').replace('"', "'"), | ||
) | ||
buf += l | ||
except SystemExit: | ||
sys.exit(0) | ||
except: | ||
|
@@ -57094,6 +57181,67 @@ def convHeapProfSample(path, scripts=[]): | |
if totalLength: | ||
UtilMgr.deleteProgress() | ||
|
||
# print meta info # | ||
for x in ( | ||
["packages_list", "trace_config", "system_info"] | ||
if SysMgr.warnEnable | ||
else [] | ||
): | ||
if not x in packets: | ||
continue | ||
SysMgr.printWarn( | ||
("[%s]: " % x) + UtilMgr.convDict2Str(packets[x]), True | ||
) | ||
|
||
# process profile info # | ||
profData = packets.get("profile_packet") | ||
if not profData: | ||
SysMgr.printErr("no profiled sample data") | ||
return -1 | ||
|
||
# process profile samples # | ||
# callstack_id, self_allocated, self_freed, alloc_count, free_count # | ||
for p in profData if isinstance(profData, list) else [profData]: | ||
pdata = p.get("process_dumps") | ||
if not pdata: | ||
continue | ||
samples = pdata.pop("samples") | ||
|
||
# print profiling info # | ||
if SysMgr.warnEnable: | ||
SysMgr.printWarn( | ||
"[prof_info]: " + UtilMgr.convDict2Str(pdata), True | ||
) | ||
|
||
# save callstack info # | ||
for s in samples: | ||
cid = s.pop("callstack_id") | ||
if not cid: | ||
continue | ||
|
||
if not cid in stacks: | ||
stacks[cid] = {} | ||
|
||
# merge stats # | ||
for n, v in s.items(): | ||
stacks[cid][n] = long(stacks[cid].get(n, 0)) + long(v) | ||
|
||
# process intenred data # | ||
""" | ||
mapping_paths: object path | ||
mappings: paths | ||
function_names: function names | ||
frames: function names, mappings | ||
callstacks: frames | ||
""" | ||
internedData = packets.get("interned_data") | ||
if not internedData: | ||
SysMgr.printErr("no profiled intenred data") | ||
return -1 | ||
for x in internedData: | ||
for n, v in x.items(): | ||
print(n, v) | ||
|
||
@staticmethod | ||
def convSimplePerfSample(path, scripts=[]): | ||
# read scripts from file # | ||
|