From 573fe56595e4b4de425a35bb2e1bdd21b289b96b Mon Sep 17 00:00:00 2001 From: aodongbiao Date: Sat, 6 May 2023 13:05:48 +0000 Subject: [PATCH 1/3] [rom_ram_analyzer]1. add baseline to result. 2. refactored the format of xml of ram Signed-off-by: aodongbiao --- tools/rom_ram_analyzer/lite_small/README.md | 13 +- .../lite_small/pkgs/basic_tool.py | 77 +++++- .../pkgs/rom_ram_baseline_collector.py | 67 +++++ .../rom_ram_analyzer/lite_small/src/config.py | 11 +- .../lite_small/src/config.yaml | 2 + .../lite_small/src/rom_analysis.py | 49 +++- tools/rom_ram_analyzer/standard/README.md | 126 ++++++--- .../standard/pkgs/basic_tool.py | 13 + .../pkgs/rom_ram_baseline_collector.py | 67 +++++ .../rom_ram_analyzer/standard/ram_analyzer.py | 256 +++++++++++++----- .../rom_ram_analyzer/standard/rom_analyzer.py | 50 +++- 11 files changed, 584 insertions(+), 147 deletions(-) create mode 100644 tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py create mode 100644 tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py diff --git a/tools/rom_ram_analyzer/lite_small/README.md b/tools/rom_ram_analyzer/lite_small/README.md index 859aac6..d46209a 100644 --- a/tools/rom_ram_analyzer/lite_small/README.md +++ b/tools/rom_ram_analyzer/lite_small/README.md @@ -27,6 +27,7 @@ 1. 关于NOTFOUND:表示对应的编译产物没有在BUILD.gn的扫描结果中匹配(包括模糊匹配)到 1. 本工具是基于gn的template进行匹配,如果新增了自定义的template,则需要相应在代码中进行配置 1. 由于本工具是进行的静态扫描,且部分gn文件中使用了较为复杂的gn语法,因此本工具的**准确率无法达到100%,结果仅供参考** +1. rk3568因为主要使用的是自定义的template,所以能够在编译阶段收集更多有效信息,因此建议使用standard目录下的脚本进行分析 **子系统及部件的查找过程** @@ -51,18 +52,17 @@ xlwt==1.3.0 ``` -1. `python3 rom_analysis.py --product_name {your_product_name} --oh_path {root_path_of_oh} [-g] [-s]`运行代码,其中-g表示直接使用上次扫描的BUILD.gn的结果,-s表示直接使用已有的子系统和部件信息,默认都会重新扫描.eg: `python3 rom_analysis.py --product_name ipcamera_hispark_taurus`. +1. `python3 rom_analysis.py --product_name {your_product_name} --oh_path {root_path_of_oh} [-g] [-s] [-b]`运行代码,其中-g表示直接使用上次扫描的BUILD.gn的结果,-s表示直接使用已有的子系统和部件信息,此二者默认都会重新扫描, -b表示在结果中添加各部件的baseline信息(根据bundle.json).eg: `python3 rom_analysis.py --product_name ipcamera_hispark_taurus -b`. 1. 运行完毕会产生4个json文件及一个xls文件,如果是默认配置,各文件描述如下: - gn_info.json:BUILD.gn的分析结果 - sub_com_info.json:从bundle.json中进行分析获得的各部件及其对应根目录的信息 - {product_name}_product.json:该产品实际的编译产物信息,根据config.yaml进行收集 - - {product_name}_result.json:各部件的rom大小分析结果 - - {product_name}_result.xls:各部件的rom大小分析结果 + - **{product_name}_result.json:各部件的rom大小分析结果** + - **{product_name}_result.xls:各部件的rom大小分析结果** + - rom_ram_baseline.json:各部件在bundle.json中定义的rom和ram的基线 ## 新增对产品的支持 -*rk3568因为主要使用的是自定义的template,所以能够在编译阶段收集更多有效信息,因此建议使用standard目录下的脚本进行分析* - 在config.yaml中进行配置即可,格式说明如下: ```yaml ipcamera_hispark_taurus: # 产品名称,需要和命令行参数中的-p参数一致 @@ -100,3 +100,6 @@ ipcamera_hispark_taurus: # 产品名称,需要和命令行参数中的-p参数 ## 后续工作 1. 对target(xxx,yyy)中,xxx/yyy为变量的情况可进一步优化 +1. 重构 +1. 在config.yaml中允许人为配置以进一步提高准确性 +1. 单位自适应 diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py b/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py index 660a04c..b182b29 100644 --- a/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py +++ b/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py @@ -20,6 +20,40 @@ import os import re import glob from typing import * +import unittest + +__all__ = ["translate_str_unit", "BasicTool", "do_nothing", "get_unit"] + + +def get_unit(x: str) -> str: + pattern = r"[a-z|A-Z]*$" + unit = re.search(pattern, x).group() + return unit + + +class TestGetUnit(unittest.TestCase): + def test_TB(self): + self.assertEqual(get_unit("1TB"), "TB") + + +def translate_str_unit(x: str, dest: str, prefix: str = "~") -> float: + src_unit = get_unit(x) + trans_dict: Dict[str, int] = { + "Byte": 1, + "byte": 1, + "KB": 1024, + "kb": 1024, + "MB": 1024*1024, + "M": 1024*1024, + "GB": 1024*1024*1024, + "G": 1024*1024*1024 + } + if src_unit not in trans_dict.keys(): + raise Exception( + f"unsupport unit: {src_unit}. only support {list(trans_dict.keys())}") + x = float(x.lstrip(prefix).rstrip(src_unit)) + return round(x*(trans_dict.get(src_unit)/trans_dict.get(dest)),2) + def do_nothing(x: Any) -> Any: @@ -138,8 +172,43 @@ class BasicTool: return output +class TestUnitTrans(unittest.TestCase): + def test_Byte(self): + self.assertEqual(translate_str_unit("~1MB", "KB"), 1024.00) + + # def test_byte(self): + # self.assertEqual(translate_str_unit("1byte"), 1) + + # def test_KB(self): + # self.assertEqual(translate_str_unit("1KB"), 1024) + + # def test_kb(self): + # self.assertEqual(translate_str_unit("1kb"), 1024) + + # def test_MB(self): + # self.assertEqual(translate_str_unit("1MB"), 1024*1024) + + # def test_M(self): + # self.assertEqual(translate_str_unit("1M"), 1024*1024) + + # def test_GB(self): + # self.assertEqual(translate_str_unit("1GB"), 1024*1024*1024) + + # def test_G(self): + # self.assertEqual(translate_str_unit("1G"), 1024*1024*1024) + + # def test_TB(self): + # with self.assertRaises(Exception): + # translate_str_unit("1TB") + + # def test_prefix(self): + # self.assertEqual(translate_str_unit("~1MB"), 1024*1024) + + if __name__ == '__main__': - res = BasicTool.grep_ern("^( *)ohos_prebuilt_shared_library", "/home/aodongbiao/oh", include="BUILD.gn", exclude=("/home/aodongbiao/oh/out","doc", ".ccache"), post_handler=lambda x: x.split('\n')) - for i in res: - if "oh/out" in i: - print(i) + # res = BasicTool.grep_ern("^( *)ohos_prebuilt_shared_library", "/home/aodongbiao/oh", include="BUILD.gn", exclude=("/home/aodongbiao/oh/out","doc", ".ccache"), post_handler=lambda x: x.split('\n')) + # for i in res: + # if "oh/out" in i: + # print(i) + + unittest.main() diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py b/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py new file mode 100644 index 0000000..a217950 --- /dev/null +++ b/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py @@ -0,0 +1,67 @@ + +if __name__ == '__main__': + from basic_tool import BasicTool +else: + from pkgs.basic_tool import BasicTool +from typing import Dict, Any +import unittest +import json +import logging + +class RomRamBaselineCollector: + """collect baseline of rom and ram from bundle.json + """ + @classmethod + def _put(cls, result_dict: Dict, subsystem_name: str, component_name: str, rom_size: str, ram_size: str, bundle_path:str) -> None: + if not result_dict.get(subsystem_name): + result_dict[subsystem_name] = dict() + result_dict[subsystem_name][component_name] = dict() + result_dict[subsystem_name][component_name]["rom"] = rom_size + result_dict[subsystem_name][component_name]["ram"] = ram_size + result_dict[subsystem_name][component_name]["bundle.json"] = bundle_path + + @classmethod + def collect(cls, oh_path: str) -> Dict[str, Dict]: + def post_handler(x:str)->list: + x = x.split("\n") + y = [item for item in x if item] + return y + bundle_list = BasicTool.execute(cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) + rom_ram_baseline_dict: Dict[str, Dict] = dict() + for bundle in bundle_list: + with open(bundle, 'r', encoding='utf-8') as f: + content: Dict[str, Any] = json.loads(f.read()) + component_info = content.get("component") + if not component_info: + logging.warning(f"{bundle} has no field of 'component'.") + continue + component_name = component_info.get("name") + subsystem_name = component_info.get("subsystem") + rom_baseline = component_info.get("rom") + ram_baseline = component_info.get("ram") + if not (subsystem_name or rom_baseline or ram_baseline): + logging.warning(f"subsystem=\"{subsystem_name}\", rom=\"{rom_baseline}\", ram=\"{ram_baseline}\" in {bundle}") + cls._put(rom_ram_baseline_dict, subsystem_name, component_name, rom_baseline, ram_baseline, bundle) + return rom_ram_baseline_dict + + +class TestRomRamBaselineCollector(unittest.TestCase): + + def test_collect(self): + RomRamBaselineCollector.collect("/mnt/data/aodongbiao/codechecker_oh") + ... + + def test_bundle(self): + def post_handler(x:str)->list: + x = x.split("\n") + y = [item for item in x if item] + return y + oh_path = "/mnt/data/aodongbiao/codechecker_oh" + bundle_list = BasicTool.execute(cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) + print(bundle_list) + + + +if __name__ == '__main__': + + unittest.main() diff --git a/tools/rom_ram_analyzer/lite_small/src/config.py b/tools/rom_ram_analyzer/lite_small/src/config.py index a557af6..b187bb1 100644 --- a/tools/rom_ram_analyzer/lite_small/src/config.py +++ b/tools/rom_ram_analyzer/lite_small/src/config.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This file is a configuration for scaning the BUILD.gn to collection compile +# This file is a configuration for scaning the BUILD.gn to collection compile # products. @@ -43,14 +43,16 @@ def parse_args(): parser.add_argument("-o", "--oh_path", type=str, default=".", help="root path of openharmony") parser.add_argument("-g", "--recollect_gn", - action="store_false", help="recollect gn info or not") + action="store_false", help="recollect gn info or not(-g)") parser.add_argument("-s", "--recollect_sc", action="store_false", - help="recollect subsystem_component info or not") + help="recollect subsystem_component info or not(-s)") + parser.add_argument("-b", "--baseline", action="store_true", + help="add baseline of component to the result(-b) or not.") args = parser.parse_args() return args -logging.basicConfig(level=logging.INFO) +logging.basicConfig(level=logging.NOTSET) _args = parse_args() # # global variables @@ -60,6 +62,7 @@ result_dict: Dict[str, Any] = dict() project_path = BasicTool.abspath(_args.oh_path) product_name = _args.product_name recollect_gn = _args.recollect_gn +baseline = _args.baseline _recollect_sc = _args.recollect_sc _sc_json: Dict[Text, Text] = configs.get("subsystem_component") _sc_save = _sc_json.get("save") diff --git a/tools/rom_ram_analyzer/lite_small/src/config.yaml b/tools/rom_ram_analyzer/lite_small/src/config.yaml index f3394b2..67073f2 100644 --- a/tools/rom_ram_analyzer/lite_small/src/config.yaml +++ b/tools/rom_ram_analyzer/lite_small/src/config.yaml @@ -12,6 +12,7 @@ # limitations under the License. + # 注意:如果target_type有了更改,要相应改变config.py中collector_config target_type: - shared_library @@ -44,6 +45,7 @@ default_extension: default_prefix: shared_library: lib static_library: lib + # black list for command 'grep', it should be the subdirectory of the root path of oh black_list: - .repo diff --git a/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py b/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py index f827b03..ab90aff 100644 --- a/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py +++ b/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py @@ -29,10 +29,11 @@ from threading import RLock import collections from config import result_dict, collector_config, configs, \ - project_path, sub_com_dict, product_name, recollect_gn + project_path, sub_com_dict, product_name, recollect_gn, baseline from pkgs.basic_tool import BasicTool from pkgs.gn_common_tool import GnCommonTool from pkgs.simple_excel_writer import SimpleExcelWriter +from pkgs.rom_ram_baseline_collector import RomRamBaselineCollector from misc import gn_lineno_collect @@ -149,7 +150,7 @@ class RomAnalysisTool: return product_dict @classmethod - def _put(cls, sub: str, com: str, unit: Dict, rom_size_dict: Dict): + def _put(cls, sub: str, com: str, unit: Dict, rom_size_dict: Dict, com_size_baseline: str = str()): size = unit.get("size") if not rom_size_dict.get("size"): # 总大小 rom_size_dict["size"] = 0 @@ -164,6 +165,10 @@ class RomAnalysisTool: rom_size_dict[sub][com]["size"] = 0 rom_size_dict[sub][com]["count"] = 0 + if (sub != "NOTFOUND" and sub != "UNDEFINED" and com != "NOTFOUND" and com != "UNDEFINED") \ + and (not rom_size_dict.get(sub).get(com).get("baseline")) and baseline: + rom_size_dict[sub][com]["baseline"] = com_size_baseline + rom_size_dict[sub][com]["filelist"].append(unit) rom_size_dict[sub][com]["size"] += size rom_size_dict[sub][com]["count"] += 1 @@ -228,10 +233,13 @@ class RomAnalysisTool: return str(), str(), str() @classmethod - def _save_as_xls(cls, result_dict: Dict, product_name: str) -> None: + def _save_as_xls(cls, result_dict: Dict, product_name: str, baseline: bool) -> None: logging.info("saving as xls...") header = ["subsystem_name", "component_name", "output_file", "size(Byte)"] + if baseline: + header = ["subsystem_name", "component_name", "baseline", + "output_file", "size(Byte)"] tmp_dict = copy.deepcopy(result_dict) excel_writer = SimpleExcelWriter("rom") excel_writer.set_sheet_header(headers=header) @@ -241,6 +249,7 @@ class RomAnalysisTool: component_start_row = 1 component_end_row = 0 component_col = 1 + baseline_col = 2 del tmp_dict["size"] for subsystem_name in tmp_dict.keys(): subsystem_dict = tmp_dict.get(subsystem_name) @@ -255,6 +264,9 @@ class RomAnalysisTool: component_name) component_size = component_dict.get("size") component_file_count = component_dict.get("count") + component_baseline = component_dict.get("baseline") + if component_baseline: + del component_dict["baseline"] del component_dict["count"] del component_dict["size"] component_end_row += component_file_count @@ -262,10 +274,17 @@ class RomAnalysisTool: for fileinfo in component_dict.get("filelist"): file_name = fileinfo.get("file_name") file_size = fileinfo.get("size") - excel_writer.append_line( - [subsystem_name, component_name, file_name, file_size]) + line = [subsystem_name, component_name, + file_name, file_size] + if baseline: + line = [subsystem_name, component_name, + component_baseline, file_name, file_size] + excel_writer.append_line(line) excel_writer.write_merge(component_start_row, component_col, component_end_row, component_col, component_name) + if baseline: + excel_writer.write_merge(component_start_row, baseline_col, component_end_row, baseline_col, + component_baseline) component_start_row = component_end_row + 1 excel_writer.write_merge(subsystem_start_row, subsystem_col, subsystem_end_row, subsystem_col, subsystem_name) @@ -278,12 +297,16 @@ class RomAnalysisTool: @ classmethod def analysis(cls, product_name: str, product_dict: Dict[str, List[str]]): logging.info("start analyzing...") + rom_ram_baseline: Dict[str, Dict] = RomRamBaselineCollector.collect( + project_path) + with open("rom_ram_baseline.json", 'w', encoding='utf-8') as f: + json.dump(rom_ram_baseline, f, indent=4) gn_info_file = configs["gn_info_file"] with open(gn_info_file, 'r', encoding='utf-8') as f: gn_info = json.load(f) query_order: Dict[str, List[str] ] = configs[product_name]["query_order"] - query_order["etc"] = configs["target_type"] # etc会查找所有的template + query_order["etc"] = configs["target_type"] # etc会查找所有的template rom_size_dict: Dict = dict() for t, l in product_dict.items(): for f in l: # 遍历所有文件 @@ -311,13 +334,21 @@ class RomAnalysisTool: continue d["size"] = size d["file_name"] = f.replace(project_path, "") + if rom_ram_baseline.get(d["subsystem_name"]) and rom_ram_baseline.get(d["subsystem_name"]).get(d["component_name"]): + component_rom_baseline = rom_ram_baseline.get( + d["subsystem_name"]).get(d["component_name"]).get("rom") cls._put(d["subsystem_name"], - d["component_name"], d, rom_size_dict) + d["component_name"], d, rom_size_dict, component_rom_baseline) + if d["component_name"] == "unionman_products": + print(d) find_flag = True if not find_flag: # 如果指定序列中的template都没有查找到,则模糊匹配 # fuzzy match psesudo_gn, sub, com = cls._fuzzy_match(f) if sub and com: + if rom_ram_baseline.get(sub) and rom_ram_baseline.get(sub).get(com): + component_rom_baseline = rom_ram_baseline.get( + sub).get(com).get("baseline") cls._put(sub, com, { "subsystem_name": sub, "component_name": com, @@ -325,7 +356,7 @@ class RomAnalysisTool: "description": "fuzzy match", "file_name": f.replace(project_path, ""), "size": size, - }, rom_size_dict) + }, rom_size_dict, component_rom_baseline) find_flag = True if not find_flag: # 模糊匹配都没有匹配到的,归属到NOTFOUND cls._put("NOTFOUND", "NOTFOUND", { @@ -334,7 +365,7 @@ class RomAnalysisTool: }, rom_size_dict) with open(configs[product_name]["output_name"], 'w', encoding='utf-8') as f: json.dump(rom_size_dict, f, indent=4) - cls._save_as_xls(rom_size_dict, product_name) + cls._save_as_xls(rom_size_dict, product_name, baseline) logging.info("success") diff --git a/tools/rom_ram_analyzer/standard/README.md b/tools/rom_ram_analyzer/standard/README.md index 7d48d2d..af157fe 100644 --- a/tools/rom_ram_analyzer/standard/README.md +++ b/tools/rom_ram_analyzer/standard/README.md @@ -10,7 +10,7 @@ ## 支持产品 -主要是rk3568系列,已测试产品包括rk3568 rk3568_mini_system +主要是rk3568系列,已测试产品包括rk3568、rk3568_mini_system ## 使用说明 @@ -30,32 +30,32 @@ 1. `-h`或`--help`命令查看帮助 ```shell > python3 rom_analyzer.py -h - usage: rom_analyzer.py [-h] [-v] -p PROJECT_PATH -j MODULE_INFO_JSON -n PRODUCT_NAME -d PRODUCT_DIR [-o OUTPUT_FILE] [-e EXCEL] - + usage: rom_analyzer.py [-h] [-v] -p PROJECT_PATH -j MODULE_INFO_JSON -n PRODUCT_NAME -d PRODUCT_DIR [-b] [-o OUTPUT_FILE] [-e EXCEL] + analyze rom size of component. - - optional arguments: - -h, --help show this help message and exit - -v, -version show program\'s version number and exit - -p PROJECT_PATH, --project_path PROJECT_PATH - root path of oh. eg: -p ~/oh - -j MODULE_INFO_JSON, --module_info_json MODULE_INFO_JSON + + options: + -h, --help show this help message and exit + -v, -version show program\'s version number and exit + -p PROJECT_PATH, --project_path PROJECT_PATH + root path of openharmony. eg: -p ~/openharmony + -j MODULE_INFO_JSON, --module_info_json MODULE_INFO_JSON path of out/{product_name}/packages/phone/system_module_info.json - -n PRODUCT_NAME, --product_name PRODUCT_NAME + -n PRODUCT_NAME, --product_name PRODUCT_NAME product name. eg: -n rk3568 - -d PRODUCT_DIR, --product_dir PRODUCT_DIR + -d PRODUCT_DIR, --product_dir PRODUCT_DIR subdirectories of out/{product_name}/packages/phone to be counted.eg: -d system -d vendor - -o OUTPUT_FILE, --output_file OUTPUT_FILE + -b, --baseline add baseline of component to the result(-b) or not. + -o OUTPUT_FILE, --output_file OUTPUT_FILE basename of output file, default: rom_analysis_result. eg: demo/rom_analysis_result - -e EXCEL, --excel EXCEL + -e EXCEL, --excel EXCEL if output result as excel, default: False. eg: -e True ``` 1. 使用示例 ```shell - python3 rom_analyzer.py -p ~/nomodify_oh/ -j ../system_module_info.json -n rk3568 -d system -d vendor -d updater -o demo/demo -e True + python3 rom_analyzer.py -p ~/oh/ -j ~/oh/out/rk3568/packages/phone/system_module_info.json -n rk3568 -d system -d vendor -d updater -e True -b # oh:rootpath of oh - # rk3568: product_name, same as out/{product_name} - # demo/demo: path of output file, where the second 'demo' is the basename of output file + # -b: add baseline of to the result # -e True:output result in excel format additionally ``` @@ -67,7 +67,13 @@ 子系统名: { "size": 整个子系统输出文件的总大小(单位:字节), "file_count": 整个子系统产生的文件数, - 输出文件名: 本文件的大小(单位:字节), + 部件名: { + "size": 部件的大小(单位:字节), + "file_count": 部件对应的文件数, + "baseline": 部件的baseline(根据bundle.json生成), + "编译产物文件名": 编译产物大小(单位:字节) + ... + } ... }, ... @@ -76,15 +82,15 @@ ## 附加说明 -1. 由于目前standard产品使用的基本都是自定义的template,能够有效收集更多信息,因此相较于lite_small的分析脚本,本脚本能够具有更高的准确率,请放心使用 +1. 由于目前standard产品使用的基本都是自定义的template,能够有效收集更多信息,因此相较于lite_small的分析脚本,本脚本能够具有更高的准确率,可以放心使用(不出意外的话 # ram_analyzer.py ## 功能介绍 -基于out/{product_name}/packages/phone下所有cfg文件、out/{product_name}/packages/phone/system/profile下所有xml文件,分析各进程及对应部件的ram占用(默认取Pss) +基于out/{product_name}/packages/phone下所有cfg文件、out/{product_name}/packages/phone/system/profile下所有xml文件,rom的分析结果,(rom_ram_baseline.json——可以在rom分析阶段通过-b参数生成)分析各进程及对应部件的ram占用(默认取Pss) -可供参考命令:`mkdir xml && cp $(find ~/oh/out/rk3568/packages/phone/system/profile -name *.xml | xargs) xml` +收集cfg、xml文件的可供参考命令:`mkdir xml && cp $(find ~/oh/out/rk3568/packages/phone/system/profile -name *.xml | xargs) xml` 结果以json与xls格式存储,其中,json格式是必输出的,xls格式需要-e参数控制。 @@ -104,6 +110,7 @@ 5. 准备好相关数据: 1. out/{product_name}/packages/phone下所有cfg文件,并将其放置于同一个目录中(ps:同名文件仅保存一份即可) 1. out/{product_name}/packages/phone/system/profile下所有xml文件 + 1. rom_ram_baseline.json——如果需要在结果中生成基线信息 6. 运行rom_analyzer.py产生的json结果一份(即-o参数对应的文件,默认rom_analysis_result.json) 命令介绍: @@ -111,40 +118,70 @@ 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 [-o OUTPUT_FILENAME] [-e EXCEL] - + 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] + 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 ~/oh/out/rk3568/packages/phone/system/profile - -c CFG_PATH, --cfg_path CFG_PATH + -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 + -c CFG_PATH, --cfg_path CFG_PATH path of cfg files. eg: -c ./cfgs/ - -j ROM_RESULT, --rom_result ROM_RESULT - json file produced by rom_analyzer_v1.0.py, default: ./rom_analysis_result.json.eg: -j ./demo/rom_analysis_result.json - -n DEVICE_NUM, --device_num DEVICE_NUM + -j ROM_RESULT, --rom_result ROM_RESULT + json file produced by rom_analyzer_v1.0.py, default: ./rom_analysis_result.json.eg: -j + ./demo/rom_analysis_result.json + -n DEVICE_NUM, --device_num DEVICE_NUM device number to be collect hidumper info. eg: -n 7001005458323933328a01fce16d3800 - -o OUTPUT_FILENAME, --output_filename OUTPUT_FILENAME + -b BASELINE_FILE, --baseline_file BASELINE_FILE + 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 - -e EXCEL, --excel EXCEL + -e EXCEL, --excel EXCEL if output result as excel, default: False. eg: -e True ``` 2. 使用示例: ```shell - python .\ram_analyzer.py -x .\profile\ -c .\init\ -n 7001005458323933328a01fce16d3800 -j .\rom_analysis_result.json -o /demo/demo -e True - # demo/demo: path of output file, where the second 'demo' is the basename of output file - # -e True:output result in excel format additionally + 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类似 + # -b rom_ram_baseline.json:指定rom与ram的基线信息文件(可在rom统计阶段使用-b参数生成) + # -e True:生成xls格式的结果文件 ``` +3. 生成文件说明: + 1. refactored_ram_analysis_result.json:结果文件 + 1. ram_analysis_result.json:结果文件(供看板使用) + 1. ram_analysis_result.xls:xls格式存储结果文件 + ## 输出格式说明(json) + +1. refactored_ram_analysis_result.json ```json { - 进程名:{ + "子系统名":{ + "size": 子系统下所有进程占用内存的大小(单位:Byte), + "部件名":{ + "size": 部件下所有进程占用内存的大小(单位:Byte), + "进程名":{ + "size": 本进程占用内存的大小(单位:Byte), + "elf":{ + "拉起本进程的二进制文件名": 该二进制文件的大小(单位:Byte), + } + } + } + } +} +``` + +1. ram_analysis_result.json +```json +{ + "进程名":{ "size": 本进程占用内存的大小(单位:字节), - 子系统名: { - 部件名: { - elf文件名: elf文件大小(单位:字节) + "子系统名": { + "部件名": { + "elf文件名": elf文件大小(单位:字节) ... } ... @@ -153,4 +190,9 @@ }, ... } -``` \ No newline at end of file +``` + +## 后续工作 + + +1. 考虑适当简化逻辑 \ No newline at end of file diff --git a/tools/rom_ram_analyzer/standard/pkgs/basic_tool.py b/tools/rom_ram_analyzer/standard/pkgs/basic_tool.py index 96a59ec..22458ef 100644 --- a/tools/rom_ram_analyzer/standard/pkgs/basic_tool.py +++ b/tools/rom_ram_analyzer/standard/pkgs/basic_tool.py @@ -25,6 +25,19 @@ class BasicTool: @classmethod def get_abs_path(cls, path: str) -> str: return os.path.abspath(os.path.expanduser(path)) + + @classmethod + def execute(cls, cmd: str, post_processor: Callable[[Text], Text] = lambda x:x) -> Any: + """ + 封装popen,返回标准输出的列表 + :param post_processor: 对执行结果进行处理 + :param cmd: 待执行的命令 + :return: 经处理过后的字符串列表 + + """ + output = os.popen(cmd).read() + output = post_processor(output) + return output if __name__ == '__main__': diff --git a/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py b/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py new file mode 100644 index 0000000..a217950 --- /dev/null +++ b/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py @@ -0,0 +1,67 @@ + +if __name__ == '__main__': + from basic_tool import BasicTool +else: + from pkgs.basic_tool import BasicTool +from typing import Dict, Any +import unittest +import json +import logging + +class RomRamBaselineCollector: + """collect baseline of rom and ram from bundle.json + """ + @classmethod + def _put(cls, result_dict: Dict, subsystem_name: str, component_name: str, rom_size: str, ram_size: str, bundle_path:str) -> None: + if not result_dict.get(subsystem_name): + result_dict[subsystem_name] = dict() + result_dict[subsystem_name][component_name] = dict() + result_dict[subsystem_name][component_name]["rom"] = rom_size + result_dict[subsystem_name][component_name]["ram"] = ram_size + result_dict[subsystem_name][component_name]["bundle.json"] = bundle_path + + @classmethod + def collect(cls, oh_path: str) -> Dict[str, Dict]: + def post_handler(x:str)->list: + x = x.split("\n") + y = [item for item in x if item] + return y + bundle_list = BasicTool.execute(cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) + rom_ram_baseline_dict: Dict[str, Dict] = dict() + for bundle in bundle_list: + with open(bundle, 'r', encoding='utf-8') as f: + content: Dict[str, Any] = json.loads(f.read()) + component_info = content.get("component") + if not component_info: + logging.warning(f"{bundle} has no field of 'component'.") + continue + component_name = component_info.get("name") + subsystem_name = component_info.get("subsystem") + rom_baseline = component_info.get("rom") + ram_baseline = component_info.get("ram") + if not (subsystem_name or rom_baseline or ram_baseline): + logging.warning(f"subsystem=\"{subsystem_name}\", rom=\"{rom_baseline}\", ram=\"{ram_baseline}\" in {bundle}") + cls._put(rom_ram_baseline_dict, subsystem_name, component_name, rom_baseline, ram_baseline, bundle) + return rom_ram_baseline_dict + + +class TestRomRamBaselineCollector(unittest.TestCase): + + def test_collect(self): + RomRamBaselineCollector.collect("/mnt/data/aodongbiao/codechecker_oh") + ... + + def test_bundle(self): + def post_handler(x:str)->list: + x = x.split("\n") + y = [item for item in x if item] + return y + oh_path = "/mnt/data/aodongbiao/codechecker_oh" + bundle_list = BasicTool.execute(cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) + print(bundle_list) + + + +if __name__ == '__main__': + + unittest.main() diff --git a/tools/rom_ram_analyzer/standard/ram_analyzer.py b/tools/rom_ram_analyzer/standard/ram_analyzer.py index 8d98fc4..27f99e5 100644 --- a/tools/rom_ram_analyzer/standard/ram_analyzer.py +++ b/tools/rom_ram_analyzer/standard/ram_analyzer.py @@ -14,7 +14,7 @@ # limitations under the License. # This file is to implement the rom analyzation of standard device. -# +# import argparse import copy @@ -26,6 +26,7 @@ import sys import subprocess import typing import xml.dom.minidom as dom +from typing import Dict from pprint import pprint from pkgs.simple_excel_writer import SimpleExcelWriter @@ -58,7 +59,6 @@ class HDCTool: stderr = str(cp.stderr) return device_num in stderr or device_num in stdout - @classmethod def exec(cls, args: list, output_from: str = "stdout"): cp = subprocess.run(args, capture_output=True) @@ -98,7 +98,7 @@ class RamAnalyzer: @classmethod def __parse_hidumper_mem(cls, content: typing.Text, device_num: str, ss: str = "Pss") -> typing.Dict[ - typing.Text, int]: + typing.Text, int]: """ 解析:hidumper --meme的结果 返回{process_name: pss}形式的字典 @@ -133,26 +133,31 @@ class RamAnalyzer: break if line.isspace(): continue - processed: typing.List[typing.Text] = cls.__hidumper_mem_line_process(line) - if not processed or not processed[0].isnumeric(): # 如果第一列不是数字(pid),就过 + processed: typing.List[typing.Text] = cls.__hidumper_mem_line_process( + line) + # 如果第一列不是数字(pid),就过 + if not processed or not processed[0].isnumeric(): continue name = processed[1] # 否则的话就取名字,和对应的size - size = int(processed[cls.__ss_dict.get(ss)])*1024 # kilo byte to byte + size = int(processed[cls.__ss_dict.get(ss)]) * \ + 1024 # kilo byte to byte full_process_name = find_full_process_name(name) if not full_process_name: - print(f"warning: process \"{full_process_name}\" not found in not found int the result of command \"ps -ef\"") + print( + f"warning: process \"{full_process_name}\" not found in not found int the result of command \"ps -ef\"") continue process_pss_dict[full_process_name] = size return process_pss_dict @classmethod - def process_hidumper_info(cls, device_num: str, ss:str) -> typing.Dict[str, int]: + def process_hidumper_info(cls, device_num: str, ss: str) -> typing.Dict[str, int]: """ 处理进程名与对应进程大小 """ def exec_once() -> typing.Dict[str, int]: - stdout = HDCTool.exec(["hdc", "-t", device_num, "shell", "hidumper", "--mem"]) + stdout = HDCTool.exec( + ["hdc", "-t", device_num, "shell", "hidumper", "--mem"]) name_size_dict = cls.__parse_hidumper_mem(stdout, device_num, ss) return name_size_dict @@ -179,7 +184,8 @@ class RamAnalyzer: process = info.getElementsByTagName("process")[0] process_name = process.childNodes[0].data result_dict[process_name] = list() - libs = info.getElementsByTagName("loadlibs")[0].getElementsByTagName("libpath") + 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]) @@ -197,11 +203,14 @@ class RamAnalyzer: rom_info_dict = json.load(f) elf_info_dict: typing.Dict[str, typing.Dict[str, str]] = dict() for subsystem_name in rom_info_dict.keys(): - sub_val_dict: typing.Dict[str, typing.Any] = rom_info_dict.get(subsystem_name) + sub_val_dict: typing.Dict[str, typing.Any] = rom_info_dict.get( + subsystem_name) delete_values_from_dict(sub_val_dict, ["size", "file_count"]) for component_name in sub_val_dict.keys(): - component_val_dict: typing.Dict[str, str] = sub_val_dict.get(component_name) - delete_values_from_dict(component_val_dict, ["size", "file_count"]) + component_val_dict: typing.Dict[str, str] = sub_val_dict.get( + component_name) + delete_values_from_dict(component_val_dict, [ + "size", "file_count"]) for file_name, size in component_val_dict.items(): file_basename: str = os.path.split(file_name)[-1] elf_info_dict[file_basename] = { @@ -228,7 +237,8 @@ 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(profile_path, xml_base_name), result_dict) + cls.__parse_process_xml(os.path.join( + profile_path, xml_base_name), result_dict) else: # 直接执行 if result_dict.get(process_name) is None: @@ -237,7 +247,7 @@ class RamAnalyzer: @classmethod def get_process_so_relationship(cls, xml_path: str, cfg_path: str, profile_path: str) -> typing.Dict[ - str, typing.List[str]]: + str, typing.List[str]]: """ 从out/{product_name}/packages/phone/sa_profile/merged_sa查找xml文件并处理得到进程与so的对应关系 """ @@ -267,54 +277,92 @@ class RamAnalyzer: return process_elf_dict @classmethod - def __save_result_as_excel(cls, data_dict: dict, filename: str, ss: str): + def __save_result_as_excel(cls, data_dict: dict, filename: str, ss: str, baseline_file: str): """ 保存结果到excel中 - 进程名:{ - "size": xxx, - 子系统名:{ - 部件名:{ - 二进制文件: xxx, - ... + 子系统:{ + "size": 1234, + 部件:{ + "size":123, + "base_line":124, + 进程:{ + "size":12, + "elf":{ + "elf_file_1":elf_size, + ... + } } } } """ tmp_dict = copy.deepcopy(data_dict) writer = SimpleExcelWriter("ram_info") - writer.set_sheet_header( - ["process_name", "process_size({}, KB)".format(ss), "subsystem_name","component_name", "elf_name", "elf_size(KB)"]) - process_start_r = 1 - process_end_r = 0 - process_c = 0 - subsystem_c = 2 + header = header = [ + "subsystem_name", "component_name", "component_size(ram, Byte)", "process_name", f"process_size({ss}, Byte)", "elf", "elf_size(Byte)" + ] + if baseline_file: + header = [ + "subsystem_name", "component_name", "component_size(ram, Byte)", "baseline", "process_name", f"process_size({ss}, Byte)", "elf", "elf_size(Byte)" + ] + writer.set_sheet_header(header) + subsystem_c = 0 subsystem_start_r = 1 subsystem_end_r = 0 - process_size_c = 1 + + component_c = 1 component_start_r = 1 component_end_r = 0 - component_c = 3 - for process_name in tmp_dict.keys(): - process_val_dict: typing.Dict[str, typing.Dict[str, int]] = tmp_dict.get(process_name) - process_size = process_val_dict.get("size") - delete_values_from_dict(process_val_dict, ["size"]) - for subsystem_name, subsystem_val_dict in process_val_dict.items(): # 遍历subsystem - for component_name, component_val_dict in subsystem_val_dict.items(): # 遍历component - elf_count_of_component = len(component_val_dict) - for elf_name, size in component_val_dict.items(): # 遍里elf - writer.append_line([process_name, process_size, subsystem_name, component_name, elf_name, "%.2f" % (size / 1024)]) - component_end_r += elf_count_of_component - subsystem_end_r += elf_count_of_component - # 重写component - writer.write_merge(component_start_r, component_c, component_end_r, - component_c, component_name) - component_start_r = component_end_r + 1 - process_end_r += elf_count_of_component - writer.write_merge(subsystem_start_r, subsystem_c, subsystem_end_r, subsystem_c, subsystem_name) - subsystem_start_r = subsystem_end_r+1 - writer.write_merge(process_start_r, process_c, process_end_r, process_c, process_name) - writer.write_merge(process_start_r, process_size_c, process_end_r, process_size_c, process_size) - process_start_r = process_end_r + 1 + component_size_c = 2 + baseline_c = 3 + + process_start_r = 1 + process_end_r = 0 + process_c = 4 + process_size_c = 5 + if not baseline_file: + process_c -= 1 + process_size_c -= 1 + for subsystem_name, subsystem_info in tmp_dict.items(): + subsystem_size = subsystem_info.get("size") + if subsystem_size: + del subsystem_info["size"] + for component_name, component_info in subsystem_info.items(): + component_size = component_info.get("size") + component_baseline = component_info.get("baseline") + if "size" in component_info.keys(): + del component_info["size"] + if "baseline" in component_info.keys(): + del component_info["baseline"] + for process_name, process_info in component_info.items(): + process_size = process_info.get("size") + elf_info = process_info.get("elf") + for elf_name, elf_size in elf_info.items(): + line = [subsystem_name, component_name, component_size, + process_name, process_size, elf_name, elf_size] + if baseline_file: + line = [subsystem_name, component_name, component_size, + component_baseline, process_name, process_size, elf_name, elf_size] + writer.append_line(line) + elf_count = len(elf_info) + process_end_r += elf_count + component_end_r += elf_count + subsystem_end_r += elf_count + writer.write_merge( + process_start_r, process_c, process_end_r, process_c, process_name) + writer.write_merge( + process_start_r, process_size_c, process_end_r, process_size_c, process_size) + process_start_r = process_end_r+1 + writer.write_merge(component_start_r, component_c, + component_end_r, component_c, component_name) + writer.write_merge(component_start_r, component_size_c, + component_end_r, component_size_c, component_size) + if baseline_file: + writer.write_merge(component_start_r, baseline_c, + component_end_r, baseline_c, component_baseline) + component_start_r = component_end_r + 1 + writer.write_merge(subsystem_start_r, subsystem_c, + subsystem_end_r, subsystem_c, subsystem_name) + subsystem_start_r = subsystem_end_r+1 writer.save(filename) @classmethod @@ -328,25 +376,43 @@ class RamAnalyzer: evaluator:评估elf文件的从phone下面开始的路径与service_name的关系,评判如何才是找到了 returns: 是否查找到,elf文件名,部件名,size """ - subsystem_name_list = [subsystem_name] if subsystem_name != "*" else rom_result_dict.keys() + subsystem_name_list = [ + subsystem_name] if subsystem_name != "*" else rom_result_dict.keys() for sn in subsystem_name_list: sub_val_dict = rom_result_dict.get(sn) - component_name_list = [component_name] if component_name != '*' else sub_val_dict.keys() + component_name_list = [ + component_name] if component_name != '*' else sub_val_dict.keys() for cn in component_name_list: if cn == "size" or cn == "file_count": continue - component_val_dict: typing.Dict[str, int] = sub_val_dict.get(cn) + component_val_dict: typing.Dict[str, + int] = sub_val_dict.get(cn) for k, v in component_val_dict.items(): if k == "size" or k == "file_count": continue if not evaluator(service_name, k): continue - return True, os.path.split(k)[-1],sn, cn, v + return True, os.path.split(k)[-1], sn, cn, v return False, str(), str(), str(), int() + @classmethod + def add_baseline(self, refactored_result_dict: Dict, baseline_file: str) -> None: + with open(baseline_file, 'r', encoding='utf-8') as f: + baseline_dict = json.load(f) + for subsystem_name, subsystem_info in refactored_result_dict.items(): + for component_name, component_info in subsystem_info.items(): + if component_name == "size": + continue + if not baseline_dict.get(subsystem_name): + continue + if not baseline_dict[subsystem_name].get(component_name): + continue + component_info["baseline"] = baseline_dict[subsystem_name][component_name].get( + "ram") + @classmethod def analysis(cls, cfg_path: str, xml_path: str, rom_result_json: str, device_num: str, - output_file: str, ss: str, output_excel: bool): + output_file: str, ss: str, output_excel: bool, baseline_file: str): """ process size subsystem/component so so_size """ @@ -364,7 +430,8 @@ class RamAnalyzer: rom_result_json) process_elf_dict: typing.Dict[str, typing.List[str]] = cls.get_process_so_relationship(xml_path, cfg_path, profile_path) - process_size_dict: typing.Dict[str, int] = cls.process_hidumper_info(device_num, ss) + 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() def get(key: typing.Any, dt: typing.Dict[str, typing.Any]): @@ -379,33 +446,37 @@ class RamAnalyzer: continue # 如果部件是init,特殊处理 if process_name == "init": - _, elf,_, _, size = cls.find_elf_size_from_rom_result(process_name, "startup", "init", - lambda x, y: os.path.split(y)[ - -1].lower() == x.lower(), - rom_result_dict) + _, elf, _, _, size = cls.find_elf_size_from_rom_result(process_name, "startup", "init", + lambda x, y: os.path.split(y)[ + -1].lower() == x.lower(), + rom_result_dict) result_dict[process_name] = dict() result_dict[process_name]["size"] = process_size result_dict[process_name]["startup"] = dict() result_dict[process_name]["startup"]["init"] = dict() - result_dict[process_name]["startup"]["init"][elf if len(elf) != 0 else "UNKNOWN"] = size + result_dict[process_name]["startup"]["init"][elf if len( + elf) != 0 else "UNKNOWN"] = size continue # 如果是hap,特殊处理 if (process_name.startswith("com.") or process_name.startswith("ohos.")): _, hap_name, subsystem_name, component_name, size = cls.find_elf_size_from_rom_result(process_name, "*", "*", - lambda x, y: len( - y.split( - '/')) >= 3 and x.lower().startswith( - y.split('/')[2].lower()), - rom_result_dict) + lambda x, y: len( + y.split( + '/')) >= 3 and x.lower().startswith( + y.split('/')[2].lower()), + rom_result_dict) result_dict[process_name] = dict() result_dict[process_name]["size"] = process_size result_dict[process_name][subsystem_name] = dict() result_dict[process_name][subsystem_name][component_name] = dict() - result_dict[process_name][subsystem_name][component_name][hap_name if len(hap_name) != 0 else "UNKNOWN"] = size + result_dict[process_name][subsystem_name][component_name][hap_name if len( + hap_name) != 0 else "UNKNOWN"] = size continue - so_list: list = get(process_name, process_elf_dict) # 得到进程相关的elf文件list + # 得到进程相关的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(process_name)) + print("warning: process '{}' not found in .xml or .cfg".format( + process_name)) result_dict[process_name] = dict() result_dict[process_name]["size"] = process_size result_dict[process_name]["UNKNOWN"] = dict() @@ -420,7 +491,8 @@ class RamAnalyzer: result_dict[process_name]["UNKNOWN"] = dict() result_dict[process_name]["UNKNOWN"]["UNKNOWN"] = dict() result_dict[process_name]["UNKNOWN"]["UNKNOWN"][so] = int() - print("warning: '{}' in {} not found in json from rom analysis result".format(so, process_name)) + print("warning: '{}' in {} not found in json from rom analysis result".format( + so, process_name)) continue component_name = unit.get("component_name") subsystem_name = unit.get("subsystem_name") @@ -434,9 +506,42 @@ class RamAnalyzer: if len(base_dir) != 0 and not os.path.isdir(base_dir): os.makedirs(base_dir, exist_ok=True) with open(output_file + ".json", 'w', encoding='utf-8') as f: - f.write(json.dumps(result_dict, indent=4)) + # f.write(json.dumps(result_dict, indent=4)) + json.dump(result_dict, f, indent=4) + refactored_result: Dict[str, Dict] = refacotr_result(result_dict) + if baseline_file: + cls.add_baseline(refactored_result, baseline_file) + with open(f"refactored_{output_file}.json", 'w', encoding='utf-8') as f: + json.dump(refactored_result, f, indent=4) if output_excel: - cls.__save_result_as_excel(result_dict, output_file + ".xls", ss) + cls.__save_result_as_excel( + refactored_result, output_file + ".xls", ss, baseline_file) + + +def refacotr_result(ram_result: Dict[str, Dict]) -> Dict[str, Dict]: + refactored_ram_dict: Dict[str, Dict] = dict() + for process_name, process_info in ram_result.items(): + process_size = process_info.get("size") + del process_info["size"] + for subsystem_name, subsystem_info in process_info.items(): + for component_name, component_info in subsystem_info.items(): + for elf_name, elf_size in component_info.items(): + if not refactored_ram_dict.get(subsystem_name): + refactored_ram_dict[subsystem_name] = dict() + refactored_ram_dict[subsystem_name]["size"] = 0 + if not refactored_ram_dict[subsystem_name].get(component_name): + refactored_ram_dict[subsystem_name][component_name] = dict( + ) + refactored_ram_dict[subsystem_name][component_name]["size"] = 0 + refactored_ram_dict[subsystem_name][component_name][process_name] = dict( + ) + refactored_ram_dict[subsystem_name][component_name][process_name]["size"] = process_size + refactored_ram_dict[subsystem_name][component_name][process_name]["elf"] = dict( + ) + refactored_ram_dict[subsystem_name][component_name][process_name]["elf"][elf_name] = elf_size + refactored_ram_dict[subsystem_name]["size"] += process_size + refactored_ram_dict[subsystem_name][component_name]["size"] += process_size + return refactored_ram_dict def get_args(): @@ -455,6 +560,8 @@ def get_args(): "eg: -j ./demo/rom_analysis_result.json") parser.add_argument("-n", "--device_num", type=str, required=True, help="device number to be collect hidumper info. eg: -n 7001005458323933328a01fce16d3800") + parser.add_argument("-b", "--baseline_file", type=str, default="", + help="baseline file of rom and ram generated by rom analysis.") parser.add_argument("-o", "--output_filename", default="ram_analysis_result", type=str, help="base name of output file, default: ram_analysis_result. eg: -o ram_analysis_result") parser.add_argument("-e", "--excel", type=bool, default=False, @@ -470,6 +577,7 @@ if __name__ == '__main__': rom_result = args.rom_result device_num = args.device_num output_filename = args.output_filename + baseline_file = args.baseline_file output_excel = args.excel RamAnalyzer.analysis(cfg_path, profile_path, rom_result, - device_num=device_num, output_file=output_filename, ss="Pss", output_excel=output_excel) + device_num=device_num, output_file=output_filename, ss="Pss", output_excel=output_excel, baseline_file=baseline_file) diff --git a/tools/rom_ram_analyzer/standard/rom_analyzer.py b/tools/rom_ram_analyzer/standard/rom_analyzer.py index 698130a..6443340 100644 --- a/tools/rom_ram_analyzer/standard/rom_analyzer.py +++ b/tools/rom_ram_analyzer/standard/rom_analyzer.py @@ -23,6 +23,7 @@ import typing from copy import deepcopy from typing import * +from pkgs.rom_ram_baseline_collector import RomRamBaselineCollector from pkgs.basic_tool import BasicTool from pkgs.gn_common_tool import GnCommonTool from pkgs.simple_excel_writer import SimpleExcelWriter @@ -33,6 +34,7 @@ NOTFOUND = "NOTFOUND" class RomAnalyzer: + @classmethod def __collect_product_info(cls, system_module_info_json: Text, project_path: Text) -> Dict[Text, Dict[Text, Text]]: @@ -72,9 +74,12 @@ class RomAnalyzer: return product_info_dict @classmethod - def __save_result_as_excel(cls, result_dict: dict, output_name: str): + def __save_result_as_excel(cls, result_dict: dict, output_name: str, add_baseline: bool): header = ["subsystem_name", "component_name", "output_file", "size(Byte)"] + if add_baseline: + header = ["subsystem_name", "component_name", "baseline", + "output_file", "size(Byte)"] tmp_dict = deepcopy(result_dict) excel_writer = SimpleExcelWriter("rom") excel_writer.set_sheet_header(headers=header) @@ -84,7 +89,8 @@ class RomAnalyzer: component_start_row = 1 component_end_row = 0 component_col = 1 - + if add_baseline: + baseline_col = 2 for subsystem_name in tmp_dict.keys(): subsystem_dict = tmp_dict.get(subsystem_name) subsystem_size = subsystem_dict.get("size") @@ -98,15 +104,24 @@ class RomAnalyzer: component_name) component_size = component_dict.get("size") component_file_count = component_dict.get("file_count") + baseline = component_dict.get("baseline") del component_dict["file_count"] del component_dict["size"] + if add_baseline: + del component_dict["baseline"] component_end_row += component_file_count for file_name, size in component_dict.items(): - excel_writer.append_line( - [subsystem_name, component_name, file_name, size]) + line = [subsystem_name, component_name, file_name, size] + if add_baseline: + line = [subsystem_name, component_name, + baseline, file_name, size] + excel_writer.append_line(line) excel_writer.write_merge(component_start_row, component_col, component_end_row, component_col, component_name) + if add_baseline: + excel_writer.write_merge(component_start_row, baseline_col, component_end_row, baseline_col, + baseline) component_start_row = component_end_row + 1 excel_writer.write_merge(subsystem_start_row, subsystem_col, subsystem_end_row, subsystem_col, subsystem_name) @@ -114,11 +129,17 @@ class RomAnalyzer: excel_writer.save(output_name + ".xls") @classmethod - def __put(cls, unit: typing.Dict[Text, Any], result_dict: typing.Dict[Text, Dict]): + def __put(cls, unit: typing.Dict[Text, Any], result_dict: typing.Dict[Text, Dict], baseline_dict: Dict[str, Any], add_baseline: bool): + component_name = NOTFOUND if unit.get( "component_name") is None else unit.get("component_name") subsystem_name = NOTFOUND if unit.get( "subsystem_name") is None else unit.get("subsystem_name") + + def get_rom_baseline(): + if (not baseline_dict.get(subsystem_name)) or (not baseline_dict.get(subsystem_name).get(component_name)): + return str() + return baseline_dict.get(subsystem_name).get(component_name).get("rom") size = unit.get("size") relative_filepath = unit.get("relative_filepath") if result_dict.get(subsystem_name) is None: # 子系统 @@ -130,6 +151,10 @@ class RomAnalyzer: result_dict[subsystem_name][component_name] = dict() result_dict[subsystem_name][component_name]["size"] = 0 result_dict[subsystem_name][component_name]["file_count"] = 0 + if add_baseline: + result_dict[subsystem_name][component_name]["baseline"] = get_rom_baseline( + ) + result_dict[subsystem_name]["size"] += size result_dict[subsystem_name]["file_count"] += 1 result_dict[subsystem_name][component_name]["size"] += size @@ -138,7 +163,7 @@ class RomAnalyzer: @classmethod def analysis(cls, system_module_info_json: Text, product_dirs: List[str], - project_path: Text, product_name: Text, output_file: Text, output_execel: bool): + project_path: Text, product_name: Text, output_file: Text, output_execel: bool, add_baseline: bool): """ system_module_info_json: json文件 product_dirs:要处理的产物的路径列表如["vendor", "system/"] @@ -147,6 +172,10 @@ class RomAnalyzer: output_file: basename of output file """ project_path = BasicTool.get_abs_path(project_path) + rom_baseline_dict: Dict[str, Any] = RomRamBaselineCollector.collect( + project_path) + with open("rom_ram_baseline.json", 'w', encoding='utf-8') as f: + json.dump(rom_baseline_dict, f, indent=4) phone_dir = os.path.join( project_path, "out", product_name, "packages", "phone") product_dirs = [os.path.join(phone_dir, d) for d in product_dirs] @@ -164,14 +193,14 @@ class RomAnalyzer: unit = dict() unit["size"] = size unit["relative_filepath"] = relative_filepath - cls.__put(unit, result_dict) + cls.__put(unit, result_dict, rom_baseline_dict, add_baseline) output_dir, _ = os.path.split(output_file) if len(output_dir) != 0: os.makedirs(output_dir, exist_ok=True) with open(output_file + ".json", 'w', encoding='utf-8') as f: f.write(json.dumps(result_dict, indent=4)) if output_execel: - cls.__save_result_as_excel(result_dict, output_file) + cls.__save_result_as_excel(result_dict, output_file, add_baseline) def get_args(): @@ -189,6 +218,8 @@ def get_args(): parser.add_argument("-d", "--product_dir", required=True, action="append", help="subdirectories of out/{product_name}/packages/phone to be counted." "eg: -d system -d vendor") + parser.add_argument("-b", "--baseline", action="store_true", + help="add baseline of component to the result(-b) or not.") parser.add_argument("-o", "--output_file", type=str, default="rom_analysis_result", help="basename of output file, default: rom_analysis_result. eg: demo/rom_analysis_result") parser.add_argument("-e", "--excel", type=bool, default=False, @@ -205,5 +236,6 @@ if __name__ == '__main__': product_dirs = args.product_dir output_file = args.output_file output_excel = args.excel + add_baseline = args.baseline RomAnalyzer.analysis(module_info_json, product_dirs, - project_path, product_name, output_file, output_excel) + project_path, product_name, output_file, output_excel, add_baseline) -- Gitee From 47e5d5816c6fe7c1cd33ab006f441200fc4509aa Mon Sep 17 00:00:00 2001 From: aodongbiao Date: Mon, 8 May 2023 01:49:35 +0000 Subject: [PATCH 2/3] [rom_ram_analyzer]1. delete useless and test code. 2. add copyright header to the new file. 3. format some fiels Signed-off-by: aodongbiao --- .../lite_small/pkgs/basic_tool.py | 53 +------------ .../lite_small/pkgs/gn_common_tool.py | 75 +------------------ .../pkgs/rom_ram_baseline_collector.py | 41 +++++----- .../lite_small/pkgs/simple_excel_writer.py | 12 --- .../lite_small/pkgs/simple_yaml_tool.py | 7 +- .../rom_ram_analyzer/lite_small/src/config.py | 8 +- .../lite_small/src/get_subsystem_component.py | 4 - tools/rom_ram_analyzer/lite_small/src/misc.py | 2 - .../lite_small/src/rom_analysis.py | 30 ++++---- .../pkgs/rom_ram_baseline_collector.py | 54 +++++++------ .../rom_ram_analyzer/standard/ram_analyzer.py | 7 +- .../rom_ram_analyzer/standard/rom_analyzer.py | 6 +- 12 files changed, 69 insertions(+), 230 deletions(-) diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py b/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py index b182b29..26d884c 100644 --- a/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py +++ b/tools/rom_ram_analyzer/lite_small/pkgs/basic_tool.py @@ -30,12 +30,6 @@ def get_unit(x: str) -> str: unit = re.search(pattern, x).group() return unit - -class TestGetUnit(unittest.TestCase): - def test_TB(self): - self.assertEqual(get_unit("1TB"), "TB") - - def translate_str_unit(x: str, dest: str, prefix: str = "~") -> float: src_unit = get_unit(x) trans_dict: Dict[str, int] = { @@ -50,10 +44,9 @@ def translate_str_unit(x: str, dest: str, prefix: str = "~") -> float: } if src_unit not in trans_dict.keys(): raise Exception( - f"unsupport unit: {src_unit}. only support {list(trans_dict.keys())}") + f"unsupport unit: {src_unit}. only support {list(trans_dict.keys())}") x = float(x.lstrip(prefix).rstrip(src_unit)) - return round(x*(trans_dict.get(src_unit)/trans_dict.get(dest)),2) - + return round(x*(trans_dict.get(src_unit)/trans_dict.get(dest)), 2) def do_nothing(x: Any) -> Any: @@ -170,45 +163,3 @@ class BasicTool: output = os.popen(cmd).read() output = post_processor(output) return output - - -class TestUnitTrans(unittest.TestCase): - def test_Byte(self): - self.assertEqual(translate_str_unit("~1MB", "KB"), 1024.00) - - # def test_byte(self): - # self.assertEqual(translate_str_unit("1byte"), 1) - - # def test_KB(self): - # self.assertEqual(translate_str_unit("1KB"), 1024) - - # def test_kb(self): - # self.assertEqual(translate_str_unit("1kb"), 1024) - - # def test_MB(self): - # self.assertEqual(translate_str_unit("1MB"), 1024*1024) - - # def test_M(self): - # self.assertEqual(translate_str_unit("1M"), 1024*1024) - - # def test_GB(self): - # self.assertEqual(translate_str_unit("1GB"), 1024*1024*1024) - - # def test_G(self): - # self.assertEqual(translate_str_unit("1G"), 1024*1024*1024) - - # def test_TB(self): - # with self.assertRaises(Exception): - # translate_str_unit("1TB") - - # def test_prefix(self): - # self.assertEqual(translate_str_unit("~1MB"), 1024*1024) - - -if __name__ == '__main__': - # res = BasicTool.grep_ern("^( *)ohos_prebuilt_shared_library", "/home/aodongbiao/oh", include="BUILD.gn", exclude=("/home/aodongbiao/oh/out","doc", ".ccache"), post_handler=lambda x: x.split('\n')) - # for i in res: - # if "oh/out" in i: - # print(i) - - unittest.main() diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/gn_common_tool.py b/tools/rom_ram_analyzer/lite_small/pkgs/gn_common_tool.py index 5293400..35f153b 100644 --- a/tools/rom_ram_analyzer/lite_small/pkgs/gn_common_tool.py +++ b/tools/rom_ram_analyzer/lite_small/pkgs/gn_common_tool.py @@ -204,77 +204,4 @@ class GnVariableParser: result = BasicTool.re_group_1( content, r"{} *= *(\[.*?\])".format(var), flags=re.S | re.M) result = ast.literal_eval(result.strip()) - return result - - -if __name__ == '__main__': - cc = \ - """ - target("shared_library", "mmp"){ - xxx - } - - ohos_shared_library("pinauthservice") { - sources = [ - "//base/useriam/pin_auth/services/modules/driver/src/pin_auth_driver_hdi.cpp", - "//base/useriam/pin_auth/services/modules/driver/src/pin_auth_interface_adapter.cpp", - "//base/useriam/pin_auth/services/modules/executors/src/pin_auth_executor_callback_hdi.cpp", - "//base/useriam/pin_auth/services/modules/executors/src/pin_auth_executor_hdi.cpp", - "//base/useriam/pin_auth/services/modules/inputters/src/i_inputer_data_impl.cpp", - "//base/useriam/pin_auth/services/modules/inputters/src/pin_auth_manager.cpp", - "//base/useriam/pin_auth/services/sa/src/pin_auth_service.cpp", - ] - - configs = [ - ":pin_auth_services_config", - "//base/useriam/user_auth_framework/common:iam_log_config", - "//base/useriam/user_auth_framework/common:iam_utils_config", - ] - - deps = [ - "//base/useriam/pin_auth/frameworks:pinauth_ipc", - "//third_party/openssl:libcrypto_shared", - ] - - external_deps = [ - "access_token:libaccesstoken_sdk", - "c_utils:utils", - "drivers_interface_pin_auth:libpin_auth_proxy_1.0", - "hisysevent_native:libhisysevent", - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - "safwk:system_ability_fwk", - "user_auth_framework:userauth_executors", - ] - t = [ - 1, - 2, - 3 - ] - tt = [ - aaa, - bbb, - ccc - ] - remove_configs = [ "//build/config/compiler:no_exceptions" ] - - subsystem_name = "useriam" - part_name = "pin_auth" - }""" - s = """ -updater_usb_init_cfg_path = "//base/startup/init/services/etc/init.usb.cfg" -updater_init_usb_configfs_path_cfg = - "//drivers/peripheral/usb/cfg/init.usb.configfs.cfg" -updater_faultloggerd_cfg = -"//base/hiviewdfx/faultloggerd/services/config/faultloggerd.cfg" -updater_hilog_cfg = "//base/hiviewdfx/hilog/services/hilogd/etc/hilogd.cfg" - -ohos_prebuilt_etc("updater_hilog.cfg") { -source = "${updater_hilog_cfg}" -install_images = [ "updater" ] -part_name = "updater" -} -""" - s = "\"${updater_faultloggerd_cfg}\"" - print(GnCommonTool.contains_gn_variable(s)) - ... + return result \ No newline at end of file diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py b/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py index a217950..3b4afad 100644 --- a/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py +++ b/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py @@ -1,10 +1,25 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is to collect baseline information (according to bundle.json) if __name__ == '__main__': from basic_tool import BasicTool else: from pkgs.basic_tool import BasicTool from typing import Dict, Any -import unittest import json import logging @@ -42,26 +57,4 @@ class RomRamBaselineCollector: if not (subsystem_name or rom_baseline or ram_baseline): logging.warning(f"subsystem=\"{subsystem_name}\", rom=\"{rom_baseline}\", ram=\"{ram_baseline}\" in {bundle}") cls._put(rom_ram_baseline_dict, subsystem_name, component_name, rom_baseline, ram_baseline, bundle) - return rom_ram_baseline_dict - - -class TestRomRamBaselineCollector(unittest.TestCase): - - def test_collect(self): - RomRamBaselineCollector.collect("/mnt/data/aodongbiao/codechecker_oh") - ... - - def test_bundle(self): - def post_handler(x:str)->list: - x = x.split("\n") - y = [item for item in x if item] - return y - oh_path = "/mnt/data/aodongbiao/codechecker_oh" - bundle_list = BasicTool.execute(cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) - print(bundle_list) - - - -if __name__ == '__main__': - - unittest.main() + return rom_ram_baseline_dict \ No newline at end of file diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/simple_excel_writer.py b/tools/rom_ram_analyzer/lite_small/pkgs/simple_excel_writer.py index da6f3c6..81f4431 100644 --- a/tools/rom_ram_analyzer/lite_small/pkgs/simple_excel_writer.py +++ b/tools/rom_ram_analyzer/lite_small/pkgs/simple_excel_writer.py @@ -122,15 +122,3 @@ class SimpleExcelWriter: def save(self, file_name: str): self.__book.save(file_name) - - -if __name__ == '__main__': - writer = SimpleExcelWriter(default_sheet_name="first") - writer.add_sheet("second") - writer.add_sheet("third") - writer.set_sheet_header(["h", "m", "n"]) - writer.append_line([1, 2, 3]) - writer.append_line([2, 3, 4], "second") - writer.append_line([3, 4, 5], "third") - writer.append_line([3, 2, 1]) - writer.save("demo.xls") diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/simple_yaml_tool.py b/tools/rom_ram_analyzer/lite_small/pkgs/simple_yaml_tool.py index 32cb530..084e45e 100644 --- a/tools/rom_ram_analyzer/lite_small/pkgs/simple_yaml_tool.py +++ b/tools/rom_ram_analyzer/lite_small/pkgs/simple_yaml_tool.py @@ -24,9 +24,4 @@ class SimpleYamlTool: @classmethod def read_yaml(cls, file_name: str, mode: str = "r", encoding: str = "utf-8") -> Dict: with open(file_name, mode, encoding=encoding) as f: - return yaml.load(f, Loader=SafeLoader) - - -if __name__ == '__main__': - config = SimpleYamlTool.read_yaml("/home/aodongbiao/build_static_check/tools/component_tools/rom_ram_analyzer/src/config.yaml") - print(config["black_grep_dir"]) \ No newline at end of file + return yaml.load(f, Loader=SafeLoader) \ No newline at end of file diff --git a/tools/rom_ram_analyzer/lite_small/src/config.py b/tools/rom_ram_analyzer/lite_small/src/config.py index b187bb1..a8f786a 100644 --- a/tools/rom_ram_analyzer/lite_small/src/config.py +++ b/tools/rom_ram_analyzer/lite_small/src/config.py @@ -243,10 +243,4 @@ collector_config: Tuple[BaseProcessor] = ( ) ) -__all__ = ["configs", "result_dict", "collector_config", "sub_com_dict"] - -if __name__ == '__main__': - for c in collector_config: - c.run() - with open("demo.json", 'w', encoding='utf-8') as f: - json.dump(result_dict, f) +__all__ = ["configs", "result_dict", "collector_config", "sub_com_dict"] \ No newline at end of file diff --git a/tools/rom_ram_analyzer/lite_small/src/get_subsystem_component.py b/tools/rom_ram_analyzer/lite_small/src/get_subsystem_component.py index de9fee6..2620c7f 100644 --- a/tools/rom_ram_analyzer/lite_small/src/get_subsystem_component.py +++ b/tools/rom_ram_analyzer/lite_small/src/get_subsystem_component.py @@ -139,7 +139,3 @@ class SC: __all__ = ["SC"] - -if __name__ == '__main__': - ohos_path, output_path = parse_args() - SC.run(ohos_path, output_path) diff --git a/tools/rom_ram_analyzer/lite_small/src/misc.py b/tools/rom_ram_analyzer/lite_small/src/misc.py index 79af85b..e31a1f0 100644 --- a/tools/rom_ram_analyzer/lite_small/src/misc.py +++ b/tools/rom_ram_analyzer/lite_small/src/misc.py @@ -34,8 +34,6 @@ _config = SimpleYamlTool.read_yaml("config.yaml") """ ===============info handlers=============== """ - - def extension_handler(paragraph: Text): return GnVariableParser.string_parser("output_extension", paragraph).strip('"') diff --git a/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py b/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py index ab90aff..94eac36 100644 --- a/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py +++ b/tools/rom_ram_analyzer/lite_small/src/rom_analysis.py @@ -88,7 +88,7 @@ class RomAnalysisTool: if (not sub_path) or (os.sep not in sub_path): return # 将其他目录添加到dir_list - t, sub_sub_path = sub_path.split(os.sep, 1) # 如果是c/e,分割成c,e + t, sub_sub_path = sub_path.split(os.sep, 1) # 如果是c/e,分割成c,e t = os.path.join(rela_path, t) if t in dir_list: dir_list.remove(t) @@ -107,7 +107,7 @@ class RomAnalysisTool: logging.error( f"product_name '{product_name}' not found in the config.yaml") exit(1) - product_path_dit: Dict[str, str] = dict() # 存储编译产物的类型及目录 + product_path_dit: Dict[str, str] = dict() # 存储编译产物的类型及目录 root_dir = product_dir.get("root") root_dir = os.path.join(project_path, root_dir) relative_dir: Dict[str, str] = product_dir.get("relative") @@ -120,14 +120,14 @@ class RomAnalysisTool: product_path_dit[k] = os.path.join(root_dir, v) # 查找编译产物信息 # product_dict格式: {"so": ["a.so", "b.so"]} - product_dict: Dict[str, List[str]] = dict() # 存储编译产物的名称 + product_dict: Dict[str, List[str]] = dict() # 存储编译产物的名称 for k, v in product_path_dit.items(): if not os.path.exists(v): logging.warning(f"dir '{v}' not exist") - product_dict[k] = BasicTool.find_files_with_pattern(v) # v是全路径 + product_dict[k] = BasicTool.find_files_with_pattern(v) # v是全路径 if product_dir.get("rest"): rest_dir_list: List[str] = os.listdir( - root_dir) # 除了配置在relative下之外的所有剩余目录,全部归到etc下 + root_dir) # 除了配置在relative下之外的所有剩余目录,全部归到etc下 for v in relative_dir.values(): if v in rest_dir_list: rest_dir_list.remove(v) @@ -152,14 +152,14 @@ class RomAnalysisTool: @classmethod def _put(cls, sub: str, com: str, unit: Dict, rom_size_dict: Dict, com_size_baseline: str = str()): size = unit.get("size") - if not rom_size_dict.get("size"): # 总大小 + if not rom_size_dict.get("size"): # 总大小 rom_size_dict["size"] = 0 - if not rom_size_dict.get(sub): # 子系统大小 + if not rom_size_dict.get(sub): # 子系统大小 rom_size_dict[sub]: Dict[str, Dict] = dict() rom_size_dict[sub]["size"] = 0 rom_size_dict[sub]["count"] = 0 - if not rom_size_dict.get(sub).get(com): # 部件 + if not rom_size_dict.get(sub).get(com): # 部件 rom_size_dict.get(sub)[com] = dict() rom_size_dict[sub][com]["filelist"] = list() rom_size_dict[sub][com]["size"] = 0 @@ -306,10 +306,10 @@ class RomAnalysisTool: gn_info = json.load(f) query_order: Dict[str, List[str] ] = configs[product_name]["query_order"] - query_order["etc"] = configs["target_type"] # etc会查找所有的template + query_order["etc"] = configs["target_type"] # etc会查找所有的template rom_size_dict: Dict = dict() for t, l in product_dict.items(): - for f in l: # 遍历所有文件 + for f in l: # 遍历所有文件 if os.path.isdir(f): continue find_flag = False @@ -320,11 +320,11 @@ class RomAnalysisTool: logging.warning( f"'{t}' not found in query_order of the config.yaml") break - for tn in type_list: # tn example: ohos_shared_library - if find_flag: # 如果已经在前面的template中找到了,后面的就不必再查找 + for tn in type_list: # tn example: ohos_shared_library + if find_flag: # 如果已经在前面的template中找到了,后面的就不必再查找 break output_dict: Dict[str, Dict] = gn_info.get( - tn) # 这个模板对应的所有可能编译产物 + tn) # 这个模板对应的所有可能编译产物 if not output_dict: logging.warning( f"'{tn}' not found in the {gn_info_file}") @@ -342,7 +342,7 @@ class RomAnalysisTool: if d["component_name"] == "unionman_products": print(d) find_flag = True - if not find_flag: # 如果指定序列中的template都没有查找到,则模糊匹配 + if not find_flag: # 如果指定序列中的template都没有查找到,则模糊匹配 # fuzzy match psesudo_gn, sub, com = cls._fuzzy_match(f) if sub and com: @@ -358,7 +358,7 @@ class RomAnalysisTool: "size": size, }, rom_size_dict, component_rom_baseline) find_flag = True - if not find_flag: # 模糊匹配都没有匹配到的,归属到NOTFOUND + if not find_flag: # 模糊匹配都没有匹配到的,归属到NOTFOUND cls._put("NOTFOUND", "NOTFOUND", { "file_name": f.replace(project_path, ""), "size": size, diff --git a/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py b/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py index a217950..b614451 100644 --- a/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py +++ b/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py @@ -1,18 +1,35 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is to collect baseline information (according to bundle.json) + if __name__ == '__main__': from basic_tool import BasicTool else: from pkgs.basic_tool import BasicTool from typing import Dict, Any -import unittest import json import logging + class RomRamBaselineCollector: """collect baseline of rom and ram from bundle.json """ @classmethod - def _put(cls, result_dict: Dict, subsystem_name: str, component_name: str, rom_size: str, ram_size: str, bundle_path:str) -> None: + def _put(cls, result_dict: Dict, subsystem_name: str, component_name: str, rom_size: str, ram_size: str, bundle_path: str) -> None: if not result_dict.get(subsystem_name): result_dict[subsystem_name] = dict() result_dict[subsystem_name][component_name] = dict() @@ -22,11 +39,12 @@ class RomRamBaselineCollector: @classmethod def collect(cls, oh_path: str) -> Dict[str, Dict]: - def post_handler(x:str)->list: + def post_handler(x: str) -> list: x = x.split("\n") y = [item for item in x if item] return y - bundle_list = BasicTool.execute(cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) + bundle_list = BasicTool.execute( + cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) rom_ram_baseline_dict: Dict[str, Dict] = dict() for bundle in bundle_list: with open(bundle, 'r', encoding='utf-8') as f: @@ -40,28 +58,8 @@ class RomRamBaselineCollector: rom_baseline = component_info.get("rom") ram_baseline = component_info.get("ram") if not (subsystem_name or rom_baseline or ram_baseline): - logging.warning(f"subsystem=\"{subsystem_name}\", rom=\"{rom_baseline}\", ram=\"{ram_baseline}\" in {bundle}") - cls._put(rom_ram_baseline_dict, subsystem_name, component_name, rom_baseline, ram_baseline, bundle) + logging.warning( + f"subsystem=\"{subsystem_name}\", rom=\"{rom_baseline}\", ram=\"{ram_baseline}\" in {bundle}") + cls._put(rom_ram_baseline_dict, subsystem_name, + component_name, rom_baseline, ram_baseline, bundle) return rom_ram_baseline_dict - - -class TestRomRamBaselineCollector(unittest.TestCase): - - def test_collect(self): - RomRamBaselineCollector.collect("/mnt/data/aodongbiao/codechecker_oh") - ... - - def test_bundle(self): - def post_handler(x:str)->list: - x = x.split("\n") - y = [item for item in x if item] - return y - oh_path = "/mnt/data/aodongbiao/codechecker_oh" - bundle_list = BasicTool.execute(cmd=f"find {oh_path} -name bundle.json", post_processor=post_handler) - print(bundle_list) - - - -if __name__ == '__main__': - - unittest.main() diff --git a/tools/rom_ram_analyzer/standard/ram_analyzer.py b/tools/rom_ram_analyzer/standard/ram_analyzer.py index 27f99e5..d180be7 100644 --- a/tools/rom_ram_analyzer/standard/ram_analyzer.py +++ b/tools/rom_ram_analyzer/standard/ram_analyzer.py @@ -138,9 +138,9 @@ class RamAnalyzer: # 如果第一列不是数字(pid),就过 if not processed or not processed[0].isnumeric(): continue - name = processed[1] # 否则的话就取名字,和对应的size + name = processed[1] # 否则的话就取名字,和对应的size size = int(processed[cls.__ss_dict.get(ss)]) * \ - 1024 # kilo byte to byte + 1024 # kilo byte to byte full_process_name = find_full_process_name(name) if not full_process_name: print( @@ -440,7 +440,7 @@ class RamAnalyzer: # 要么uinput_inject的对应key为mmi_uinput_inject。对于此类特殊处理,即:如果service_name找不到,但是直接执行的bin等于这个名字,也认为找到 return v - for process_name, process_size in process_size_dict.items(): # 从进程出发 + for process_name, process_size in process_size_dict.items(): # 从进程出发 if not process_name: print("warning: an empty 'process_name' has been found.") continue @@ -506,7 +506,6 @@ class RamAnalyzer: if len(base_dir) != 0 and not os.path.isdir(base_dir): os.makedirs(base_dir, exist_ok=True) with open(output_file + ".json", 'w', encoding='utf-8') as f: - # f.write(json.dumps(result_dict, indent=4)) json.dump(result_dict, f, indent=4) refactored_result: Dict[str, Dict] = refacotr_result(result_dict) if baseline_file: diff --git a/tools/rom_ram_analyzer/standard/rom_analyzer.py b/tools/rom_ram_analyzer/standard/rom_analyzer.py index 6443340..c269c09 100644 --- a/tools/rom_ram_analyzer/standard/rom_analyzer.py +++ b/tools/rom_ram_analyzer/standard/rom_analyzer.py @@ -142,12 +142,12 @@ class RomAnalyzer: return baseline_dict.get(subsystem_name).get(component_name).get("rom") size = unit.get("size") relative_filepath = unit.get("relative_filepath") - if result_dict.get(subsystem_name) is None: # 子系统 + if result_dict.get(subsystem_name) is None: # 子系统 result_dict[subsystem_name] = dict() result_dict[subsystem_name]["size"] = 0 result_dict[subsystem_name]["file_count"] = 0 - if result_dict.get(subsystem_name).get(component_name) is None: # 部件 + if result_dict.get(subsystem_name).get(component_name) is None: # 部件 result_dict[subsystem_name][component_name] = dict() result_dict[subsystem_name][component_name]["size"] = 0 result_dict[subsystem_name][component_name]["file_count"] = 0 @@ -180,7 +180,7 @@ class RomAnalyzer: project_path, "out", product_name, "packages", "phone") product_dirs = [os.path.join(phone_dir, d) for d in product_dirs] product_info_dict = cls.__collect_product_info( - system_module_info_json, project_path) # 所有产物信息 + system_module_info_json, project_path) # 所有产物信息 result_dict: Dict[Text:Dict] = dict() for d in product_dirs: file_list: List[Text] = BasicTool.find_all_files(d) -- Gitee From d201d524e92d5fbdf12f7f78a93794ed6989016e Mon Sep 17 00:00:00 2001 From: aodongbiao Date: Mon, 8 May 2023 02:14:15 +0000 Subject: [PATCH 3/3] [rom_ram_analyzer]change copyright 2022 to 2023 Signed-off-by: aodongbiao --- .../lite_small/pkgs/rom_ram_baseline_collector.py | 2 +- .../standard/pkgs/rom_ram_baseline_collector.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py b/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py index 3b4afad..32dd3af 100644 --- a/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py +++ b/tools/rom_ram_analyzer/lite_small/pkgs/rom_ram_baseline_collector.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2023 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py b/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py index b614451..af25f71 100644 --- a/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py +++ b/tools/rom_ram_analyzer/standard/pkgs/rom_ram_baseline_collector.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2023 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -- Gitee