diff --git a/tools/rom_ram_analyzer/standard/README.md b/tools/rom_ram_analyzer/standard/README.md index af157fe9..81008bfe 100644 --- a/tools/rom_ram_analyzer/standard/README.md +++ b/tools/rom_ram_analyzer/standard/README.md @@ -88,9 +88,9 @@ ## 功能介绍 -基于out/{product_name}/packages/phone下所有cfg文件、out/{product_name}/packages/phone/system/profile下所有xml文件,rom的分析结果,(rom_ram_baseline.json——可以在rom分析阶段通过-b参数生成)分析各进程及对应部件的ram占用(默认取Pss) +基于out/{product_name}/packages/phone下所有cfg文件、out/{product_name}/packages/phone/system/profile下所有json文件,rom的分析结果,(rom_ram_baseline.json——可以在rom分析阶段通过-b参数生成)分析各进程及对应部件的ram占用(默认取Pss) -收集cfg、xml文件的可供参考命令:`mkdir xml && cp $(find ~/oh/out/rk3568/packages/phone/system/profile -name *.xml | xargs) xml` +收集cfg、json文件的可供参考命令:`mkdir cfgs && cp $(find ~/oh/out/rk3568/packages/phone -name *.cfs | xargs) cfgs` 结果以json与xls格式存储,其中,json格式是必输出的,xls格式需要-e参数控制。 @@ -109,7 +109,7 @@ ``` 5. 准备好相关数据: 1. out/{product_name}/packages/phone下所有cfg文件,并将其放置于同一个目录中(ps:同名文件仅保存一份即可) - 1. out/{product_name}/packages/phone/system/profile下所有xml文件 + 1. out/{product_name}/packages/phone/system/profile下所有json 文件 1. rom_ram_baseline.json——如果需要在结果中生成基线信息 6. 运行rom_analyzer.py产生的json结果一份(即-o参数对应的文件,默认rom_analysis_result.json) @@ -118,16 +118,16 @@ 1. 使用`-h`或`--help`查看帮助 ```shell > python .\ram_analyzer.py -h - usage: ram_analyzer.py [-h] [-v] -x XML_PATH -c CFG_PATH [-j ROM_RESULT] -n DEVICE_NUM [-b BASELINE_FILE] - [-o OUTPUT_FILENAME] [-e EXCEL] + usage: ram_analyzer.py [-h] [-v] -s JSON_PATH -c CFG_PATH [-j ROM_RESULT] -n DEVICE_NUM [-b BASELINE_FILE] + [-o OUTPUT_FILENAME] [-u] [-e EXCEL] analyze ram size of component optional arguments: -h, --help show this help message and exit -v, -version show program\'s version number and exit - -x XML_PATH, --xml_path XML_PATH - path of xml file. eg: -x ~/openharmony/out/rk3568/packages/phone/system/profile + -s JSON_PATH, --json_path JSON_PATH + path of sa json file. eg: -x ~/openharmony/out/rk3568/packages/phone/system/profile -c CFG_PATH, --cfg_path CFG_PATH path of cfg files. eg: -c ./cfgs/ -j ROM_RESULT, --rom_result ROM_RESULT @@ -139,13 +139,15 @@ baseline file of rom and ram generated by rom analysis. -o OUTPUT_FILENAME, --output_filename OUTPUT_FILENAME base name of output file, default: ram_analysis_result. eg: -o ram_analysis_result + -u, --unit_adaptive unit adaptive -e EXCEL, --excel EXCEL if output result as excel, default: False. eg: -e True ``` 2. 使用示例: ```shell - python ram_analyzer.py -x xml -c cfg -j rom_analysis_result.json -n 7001005458323933328a59a140913900 -b rom_ram_baseline.json -e True - # -x xml:指定xml文件的存放路径为xml目录,-c cfg类似 + python .\ram_analyzer.py -s .\profile\ -c .\cfgs -j .\rom_analysis_result.json -n 7001005458323933328a59a140913900 -e True + # -s profile:copy到本地的out/rk3568/package/phone/system/profile目录 + # -c .\cfgs:copy到本地的out/rk3568/packages/phone下所有cfg # -b rom_ram_baseline.json:指定rom与ram的基线信息文件(可在rom统计阶段使用-b参数生成) # -e True:生成xls格式的结果文件 ``` diff --git a/tools/rom_ram_analyzer/standard/ram_analyzer.py b/tools/rom_ram_analyzer/standard/ram_analyzer.py index eada31c4..c6b9fd23 100644 --- a/tools/rom_ram_analyzer/standard/ram_analyzer.py +++ b/tools/rom_ram_analyzer/standard/ram_analyzer.py @@ -172,26 +172,28 @@ class RamAnalyzer: return exec_once() @classmethod - def __parse_process_xml(cls, file_path: str, result_dict: typing.Dict[str, typing.List[str]]): + def __parse_process_json(cls, file_path: str, result_dict: typing.Dict[str, typing.List[str]]): """ - 解析xml文件,结存存入 result_dict中,格式:{process_name: os_list} + 解析json文件,结存存入 result_dict中,格式:{process_name: os_list} 其中,so_list中是so的base_name """ - if not (os.path.isfile(file_path) and file_path.endswith(".xml")): - print("warning: {} not exist or not a xml file".format(file_path)) + if not (os.path.isfile(file_path) and file_path.endswith(".json")): + print("warning: {} not exist or not a json file".format(file_path)) return - doc = dom.parse(file_path) - info = doc.getElementsByTagName("info")[0] - process = info.getElementsByTagName("process")[0] - process_name = process.childNodes[0].data - result_dict[process_name] = list() - libs = info.getElementsByTagName( - "loadlibs")[0].getElementsByTagName("libpath") - for lib in libs: - so = lib.childNodes[0].data - result_dict.get(process_name).append(os.path.split(so)[-1]) - if debug: - print(process_name, " ", so) + with open(file_path, 'r', encoding='utf-8') as f: + j_content:typing.Dict[str, typing.Any] = json.load(f) + if "process" not in j_content.keys() or "systemability" not in j_content.keys(): + print(f"warning: {file_path} has no field 'process' or 'systemability'") + return + process_name:str = j_content.get("process") + elf_list:typing.List[str] = list() + for sa in j_content.get("systemability"): + libpath:str = sa.get("libpath") + if not libpath: + continue + elf_list.append(libpath) + result_dict[process_name] = elf_list + @classmethod def get_elf_info_from_rom_result(cls, rom_result_json: str) -> typing.Dict[str, typing.Dict[str, str]]: @@ -238,7 +240,7 @@ class RamAnalyzer: if first.endswith("sa_main"): # 由sa_main去来起进程 xml_base_name = os.path.split(path_list[0])[-1] - cls.__parse_process_xml(os.path.join( + cls.__parse_process_json(os.path.join( profile_path, xml_base_name), result_dict) else: # 直接执行 @@ -247,25 +249,15 @@ class RamAnalyzer: result_dict.get(process_name).append(os.path.split(first)[-1]) @classmethod - def get_process_so_relationship(cls, xml_path: str, cfg_path: str, profile_path: str) -> typing.Dict[ + def get_process_so_relationship(cls,cfg_path: str, profile_path: str) -> typing.Dict[ str, typing.List[str]]: """ - 从out/{product_name}/packages/phone/sa_profile/merged_sa查找xml文件并处理得到进程与so的对应关系 + parse the relationship between process and elf file """ # 从merged_sa里面收集 - xml_list = glob.glob(xml_path + os.sep + "*[.]xml", recursive=True) + # json_list = glob.glob(json_path + os.sep + "*[.]json", recursive=True) process_elf_dict: typing.Dict[str, typing.List[str]] = dict() - for xml in xml_list: - if debug: - print("parsing: ", xml) - try: - cls.__parse_process_xml(xml, process_elf_dict) - except: - print("parse '{}' failed".format(xml)) - finally: - ... - # 从system/etc/init/*.cfg中收集,如果是sa_main拉起的,则从system/profile/*.xml中进行解析 - cfg_list = glob.glob(cfg_path + os.sep + "*[.]cfg", recursive=True) + cfg_list = glob.glob(cfg_path + os.sep + "*.cfg", recursive=True) for cfg in cfg_list: if debug: print("parsing: ", cfg) @@ -429,7 +421,7 @@ class RamAnalyzer: subsystem_info["size"] = sub_size @classmethod - def analysis(cls, cfg_path: str, xml_path: str, rom_result_json: str, device_num: str, + def analysis(cls, cfg_path: str, json_path: str, rom_result_json: str, device_num: str, output_file: str, ss: str, output_excel: bool, baseline_file: str, unit_adapt:bool): """ process size subsystem/component so so_size @@ -446,8 +438,8 @@ class RamAnalyzer: so_info_dict: typing.Dict[ str, typing.Dict[str["component_name|subsystem_name|size"], str]] = cls.get_elf_info_from_rom_result( rom_result_json) - process_elf_dict: typing.Dict[str, typing.List[str]] = cls.get_process_so_relationship(xml_path, cfg_path, - profile_path) + process_elf_dict: typing.Dict[str, typing.List[str]] = cls.get_process_so_relationship(cfg_path, + json_path) process_size_dict: typing.Dict[str, int] = cls.process_hidumper_info( device_num, ss) result_dict: typing.Dict[str, typing.Dict[str, typing.Any]] = dict() @@ -493,7 +485,7 @@ class RamAnalyzer: # 得到进程相关的elf文件list so_list: list = get(process_name, process_elf_dict) if so_list is None: - print("warning: process '{}' not found in .xml or .cfg".format( + print("warning: process '{}' not found in .json or .cfg".format( process_name)) result_dict[process_name] = dict() result_dict[process_name]["size"] = process_size @@ -571,8 +563,8 @@ def get_args(): ) parser.add_argument("-v", "-version", action="version", version=f"version {VERSION}") - parser.add_argument("-x", "--xml_path", type=str, required=True, - help="path of xml file. eg: -x ~/openharmony/out/rk3568/packages/phone/system/profile") + parser.add_argument("-s", "--json_path", type=str, required=True, + help="path of sa json file. eg: -x ~/openharmony/out/rk3568/packages/phone/system/profile") parser.add_argument("-c", "--cfg_path", type=str, required=True, help="path of cfg files. eg: -c ./cfgs/") parser.add_argument("-j", "--rom_result", type=str, default="./rom_analysis_result.json", @@ -591,11 +583,13 @@ def get_args(): args = parser.parse_args() return args +def abspath(path:str)->str: + return os.path.abspath(os.path.expanduser(path)) if __name__ == '__main__': args = get_args() - cfg_path = args.cfg_path - profile_path = args.xml_path + cfg_path = abspath(args.cfg_path) + profile_path = abspath(args.json_path) rom_result = args.rom_result device_num = args.device_num output_filename = args.output_filename