def memoryAnalysis(env): from androidanalysis.utils.osUtils import listdir for process in getObservedLists(): DalvikHeapSizeList = [] DalvikHeapAllocList = [] DalvikHeapPssList = [] DalvikHeapXList = [] startMark = False firstTime = 0 dir = os.path.join(env['memmoredata_core'], get_process(process)) for filename in listdir(dir): if filename is None or filename == '': continue with open(os.path.join(dir, filename)) as memData: for line in memData: if line.find('Dalvik Heap') >= 0: firstTime, startMark = DalvikHeapX( startMark, filename, firstTime, DalvikHeapXList) DalvikHeapList = line.split() DalvikHeapPssList.append(int(DalvikHeapList[PssIndex])) DalvikHeapAllocList.append( int(DalvikHeapList[HeapAlloc])) # print DalvikHeapList[HeapFree] DalvikHeapSizeList.append(int( DalvikHeapList[HeapSize])) memoryAnalysisDraw(env, process, dir, DalvikHeapSizeList, DalvikHeapAllocList, DalvikHeapPssList, DalvikHeapXList)
def doMemAnalysis(env): # 根据 进程名称进入 相应的进程目录下面 from androidanalysis.utils.osUtils import listdir from androidanalysis.utils.SplitUtils import split for process in getObservedLists(): dir = os.path.join(env['memmoredata_core'], get_process(process)) for filename in listdir(dir): if filename is None or filename == '': continue with open(os.path.join(dir, filename)) as memData: for line in memData: # 如果包含 "TOTAL" 则 提取出后面的关键字 # 如果 total 后面的 内容 可以 被 int 来转换 则认为是全部 if "total" in line.lower(): values = split(line, " ", "\t") i = 0 for value in values: i += 1 if i == 2: if value.isdigit(): excuteMemData(process, filename, value) # print ",value:" + value pass pass pass pass
def obtainHprof(env, scene=''): for process in getObservedLists(): file1 = '/sdcard/hprof/{0}_{1}_scene.hprof'.format( process, time.strftime('%Y%m%d_%H%M%S')) runAdbCommand(env, ['shell', 'am', 'dumpheap', process, file1]) if scene != '': runAdbCommand( env, ['shell', 'mv', file1, file1.replace('scene', scene)])
def obtainpid(env, _StopMark, interval): while True: psinfo = runAdbCommand(env, ['shell', 'ps'], check=obtain_psinfo) # 判断psinfo的有效性 if not checkValue(psinfo): psinfo = runAdbCommand(env, ['shell', 'ps -ef'], check=obtain_psinfo) pass killTime = obtainKillTime() pid_index = 0 count = 0 try: # 进程号发生变更才会被检测到,如果 进程号 死掉,未起来 则不会打印 for partinfo in psinfo.split('\n'): # print partinfo if partinfo.find('PID') > 0: pid_index = partinfo.split().index('PID') for process in getObservedLists(): # print process in psinfo, "????" processsearchinfo = re.compile('%s$' % process).search(partinfo.strip()) t = time.strftime('%Y-%m-%d_%H%M%S', time.localtime()) # print ">>>>", process, "<<<<", processsearchinfo if processsearchinfo: txz_pid = partinfo.split()[pid_index] # writeLog(env, '>>>当前%s的PID为:%s' % (process, txz_pid)) # fd obtainfd(env, t, txz_pid, process) # task obtaintask(env, t, txz_pid, process) # 不允许出现多个进程 , 需要进行 打印 if isNullprocessInfo(process, key_process_pid): addProcessInfo(process, key_process_pid, txz_pid) elif not haveProcessInfo(process, key_process_pid, txz_pid): # 不存在 writeLog(env, '>>>{0}被杀,历史pid为:{1}'.format(process, str(getProcessInfo(process, key_process_pid)))) addProcessInfo(process, key_process_stopTime, killTime) addProcessInfo(process, key_process_pid, txz_pid) threading.Thread(target=getReport, args=(env, 'txz_killed', False)).start() else: pass # addProcessInfo(process, key_process_pid, txz_pid) count += 1 if count >= 2: break # else: # writeLog(env, '>>>当前系统 获取指定 进程 的PID获取失败(进程名为:' + str(getObservedLists()) + ")" + str([psinfo])) except: writeLog(env, 'error:{0}\n{1}'.format(traceback.print_exc(), str([psinfo]))) if _StopMark.value: break time.sleep(interval) writeLog(env, "fd 和 task 获取完成")
def genEnv(dev=None, test=False, myenv={}): if test: env = myenv else: env = {} if dev is not None: env['dev'] = dev if dev is None: env['tag'] = time.strftime('%Y%m%d_%H%M%S') else: # env['tag'] = dev.replace(':','_').replace('?','_').replace('?','_') + '_' + base64.b64encode(dev) + '_' + time.strftime('%Y%m%d_%H%M%S') env['tag'] = base64.b64encode(dev) + '_' + time.strftime('%Y%m%d_%H%M%S') print env['tag'] env['dir'] = env['tag'] env['dir'] = os.path.join("../build", env['dir']) mkdirs(env['dir']) # 只有一台设备就创建时间名的目录,多台设备就创建含设备编码的目录 # 循环创建 进程相关的文件夹 for process in getObservedLists(): initProcess(env, process) env['memmoredata_core'] = os.path.join(env['dir'], 'memmoredata_core') mkdirs(env['memmoredata_core']) env['flow'] = os.path.join(env['dir'], 'flow') mkdirs(env['flow']) env['result'] = os.path.join(env['dir'], 'Result') mkdirs(env['result']) env['memlogpath'] = os.path.join(env['dir'], 'memdata') mkdirs(env['memlogpath']) env['top_thread_logpath'] = os.path.join(env['dir'], 'top_thread_data') mkdirs(env['top_thread_logpath']) env['top_process_logpath'] = os.path.join(env['dir'], 'top_process_data') mkdirs(env['top_process_logpath']) env['syslogpath'] = os.path.join(env['dir'], 'SYSLog') mkdirs(env['syslogpath']) env['hprof'] = os.path.join(env['dir'], 'Hprof') mkdirs(env['hprof']) env['pullApk'] = os.path.join(env['dir'], 'pullApk') mkdirs(env['pullApk']) env['log'] = open(env['dir'] + '/preburning.log', 'w') return env
def mymem(env, _StopMark, interval): # runAdbCommand(env,['connect','127.0.0.1:62001']) while True: if env['dev'] in readDeviceList(): writeLog(env, '>>>------------抓取内存数据------------') for process in getObservedLists(): # 抓取指定进程名称的内存信息 writeProcessMem(env, process) writeProcessMem(env) # 抓取总体的内存信息 # 休眠1s 继续执行 ,什么时候结束? if _StopMark.value: break time.sleep(interval) writeLog(env, ">>>------------抓取内存数据------------ 完成")
def excuteTrend(env, path, startFile, endFile): obtainMemInfo(os.path.join(path.decode('utf-8').encode('gbk'), startFile), key_process_begin_mem) obtainMemInfo(os.path.join(path.decode('utf-8').encode('gbk'), endFile), key_process_end_mem) writeLog(env, startFile) writeLog(env, endFile) consumeHourValue = consumeMin(testTime(startFile, endFile)) if not consumeHourValue: writeLog(env, 'kill时间点异常,起始就发生kill') return writeLog(env, "本次统计的数据{0} 到 {1}".format(startFile, endFile)) for process in getObservedLists(): begin_mem = getProcessInfo(process, key_process_begin_mem, [0])[0] end_mem = getProcessInfo(process, key_process_end_mem, [0])[0] ratio = rakeRatio(begin_mem, end_mem, consumeHourValue) writeLog( env, "{0} 进程 ----起始内存:{1:.2f}MB,结束内存:{2:.2f}MB,斜率:{3}".format( process, begin_mem, end_mem, ratio))
def memTrend(env): killtime = 0 for process in getObservedLists(): # 取出最小值 process_info = getProcessInfo(process, key_process_stopTime) if process_info is not None: stop_time_lists = sorted(process_info) # 排序 从 小到大 if killtime == 0 or killtime > stop_time_lists[0]: killtime = stop_time_lists[0] pass pass # writeLog(env, "killtime:" + str(killtime)) mlist = [] from androidanalysis.constant.Constant import VERIFY_MEM_FILE_SIZE if killtime != 0: killtime = realKillTime(killtime) # writeLog(env, "realtime:" + str(killtime)) for root, dirs, files in os.walk(env['memlogpath']): if root == env['memlogpath']: # 获取当前目录底下的 for file in files: fileTime = time_pattern.search(file).group() if fileTime < killtime and os.path.getsize( os.path.join(root, file)) > VERIFY_MEM_FILE_SIZE: mlist.append(file) if mlist: excuteTrend(env, env['memlogpath'], mlist[0], mlist[-1]) else: for root, dirs, files in os.walk(env['memlogpath']): if root == env['memlogpath']: for file in files: if os.path.getsize(os.path.join( root, file)) > VERIFY_MEM_FILE_SIZE: mlist.append(file) break pass # print mlist if mlist: excuteTrend(env, env['memlogpath'], mlist[0], mlist[-1])
def excute(env, _StopMark, testModel): from androidanalysis.utils.CpuUtils import start_monitor_pid_cpu_usage, start_monitor_thread_cpu_usage from androidanalysis.constant.ObservedProcess import getObservedLists from AnalysisPid import getPidFromPackage from androidanalysis.constant.Process_Constant import get_info global errorstauts global sceneTimer info = get_info() writeLog(env, '>>>开始抓取TOP数据') # 定时启动项 mytimer(env, _StopMark) # FIXMe 暂时注释 timerMark = True # _top_thread_cmd = ['adb', '-s', env['dev'], 'shell', 'top', '-t', '-d', '1', '-n', '1'] # _top_thread_p = subprocess.Popen(_top_thread_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # _syslog_cmd = ['adb', '-s', env['dev'], 'logcat', '-v', 'time'] # _syslog_p = subprocess.Popen(_syslog_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # _top_process_cmd = ['adb', '-s', env['dev'], 'shell', 'top', '-d', '1', '-n', '1'] # _top_process_p = subprocess.Popen(_top_process_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) from androidanalysis.utils.DeviceInfo import start_get_sys_log start_get_sys_log(env, _StopMark) count = 51200 while not _StopMark.value: if os.path.exists(stopApkMark): try: sceneTimer.cancel() except: pass stopPreburn(env, testModel) os.remove(stopApkMark) obtainHprof(env) easytime = time.strftime('%Y%m%d_%H%M%S', time.localtime()) Top_thread_file_name = 'Top_thread_data_%s.log' % (easytime) Top_process_file_name = 'Top_process_data_%s.log' % (easytime) with open(os.path.join(env['top_thread_logpath'], Top_thread_file_name), 'wb') as top_thread_file, \ open(os.path.join(env['top_process_logpath'], Top_process_file_name), 'wb') as top_process_file: while count: writeLog(env, ">>>------------抓取cpu数据------------") if os.path.exists(stopApkMark): try: sceneTimer.cancel() except: pass stopPreburn(env, testModel) os.remove(stopApkMark) obtainHprof(env) count -= 1 if _StopMark.value: break else: def write2File(log_file, content): log_file.writelines(content) log_file.flush() def writeCpuThreadCallback(process, parent_pid, pid, usage): recordtime = time.strftime('%Y%m%d_%H%M%S', time.localtime()) write2File(top_thread_file, "{0},{1},{2},{3},{4}\n".format(recordtime, process, parent_pid, pid, usage)) def writeCpuPidCallback(process, parent_pid, pid, usage): recordtime = time.strftime('%Y%m%d_%H%M%S', time.localtime()) write2File(top_process_file, "{0},{1},{2},{3},{4}\n".format(recordtime, process, parent_pid, pid, usage)) for process in getObservedLists(): pid = getPidFromPackage(env, process) if pid == -1: # writeLog(env, "can't find process:" + process) continue start_monitor_pid_cpu_usage("", 0.1, pid, writeCpuPidCallback) start_monitor_thread_cpu_usage("", 0.1, pid, writeCpuThreadCallback) top_process_file.write("\n") top_thread_file.write("\n") if errorstauts: _StopMark.value = True time.sleep(info.interval_cpu) if _StopMark.value: try: sceneTimer.cancel() except: pass from androidanalysis.utils.TimerUtils import mytimercancel mytimercancel(env, timerMark) break top_thread_file.close() top_process_file.close() count = 51200 if errorstauts: _StopMark.value = True writeLog(env, ">>>------------抓取cpu数据------------ 完成")
def beginTest(info, _StopMark): # removeStateFile(stopApkMark) # 删除 文件 # removeStateFile(successMark) # setObservedLists(processlist) # 取出 被观察的 包名 # env = genEnv(dev) # openlog(env) # 开启所有的日志 # killApkPid(env, 'com.txznet.txz') env = init_env(_StopMark) if env is None: writeLog({}, "env error") return startTime = obtainTime() writeLog(env, "开始抓取数据 cpu mem pid 的数据") while True: excute(env, _StopMark, info.mode) if _StopMark.value: mytimercancel(env, True) break checkConnect(env, False) writeLog(env, "开始为您分析数据") try: global sceneTimer sceneTimer.cancel() except: pass endTime = obtainTime() stopPreburn(env, info.mode) runAdbCommand(env, [ 'pull', '/proc/net/xt_qtaguid/stats', os.path.join(env['flow'], 'stats_' + str(time.time())) ]) # writeLog(env, # '-------------------------------------------Test Over-------------------------------------------\ntest scene:{0}'.format( # ','.join(s.decode('gbk').encode('utf-8') for s in sceneList))) writeLog(env, "获取日志信息【1个小时抓取一次】") getReport(env, 'TestOver', Timeing=False) writeLog(env, "获取当前的hprof") obtainHprof(env, 'end') time.sleep(3) writeLog(env, "拉取文件 asr hprof 文件到电脑上") runAdbCommand(env, ['pull', '/sdcard/preburning/asr', env['result']]) runAdbCommand(env, ['pull', '/sdcard/hprof/', env['hprof']]) writeLog( env, '-------------------------------------------开始数据统计-------------------------------------------------------------' ) from androidanalysis.constant.ObservedProcess import printInfos printInfos(env) mHouer = consumeHour(consumeTime(startTime, endTime)) writeLog( env, '始于:{0},终于:{1},总试耗时:{2:.2f}H'.format(str(startTime), str(endTime), mHouer)) flowCounter(env, obtainuserid(env), mHouer) for process in getObservedLists(): killed_count = getprocessInfoKeyLen(process, key_process_pid) if killed_count == 0: writeLog(env, '进程:{0},未启动过;'.format(process)) else: writeLog(env, '进程:{0},被杀{1}次;'.format(process, killed_count - 1)) pass writeLog(env, '--------------------内存数据-----------------------') memTrend(env) # 通过dumpsys meminfo 的数据都画在一张图上 exc_memdata(env) # 分别绘制各自的内存数据 都 各自的图上 memoryAnalysis(env) writeLog(env, '--------------------CPU数据-----------------------') commonanalysedata(env) obtianCrashCount(env) writeLog( env, '-------------------------------------------统计结束-------------------------------------------------------------' ) closeProc(successMark) # print threading.active_count() pl.show(block=True) # 所有图关闭,退出阻塞