当前位置: 首页 > news >正文

曼朗策划网站建设中国建设人才服务信息网是正规网站

曼朗策划网站建设,中国建设人才服务信息网是正规网站,wordpress里面的rss订阅,京润珍珠企业网站优化一、前言 百度APP包体积经过一期优化#xff0c;如无用资源清理#xff0c;无用类下线#xff0c;Xcode编译相关优化#xff0c;体积已经有了明显的减少。但是优化后APP包体积在iPhone11上仍有350M的空间占用。与此同时百度APP作为百度的旗舰APP#xff0c;业务迭代非常多…一、前言 百度APP包体积经过一期优化如无用资源清理无用类下线Xcode编译相关优化体积已经有了明显的减少。但是优化后APP包体积在iPhone11上仍有350M的空间占用。与此同时百度APP作为百度的旗舰APP业务迭代非常多且迅速体积优化和防劣化仍然是当前阶段的一个核心任务。因此百度APP开启了粒度更小修复风险更高的无用方法清理相关工作。期望通过无用方法清理有效降低百度APP的包体积同时删除项目中的无用方法冗余代码提高代码的整洁度。 百度APP iOS端包体积优化实践系列文章回顾 《百度APP iOS端包体积50M优化实践(一)总览》 《百度APP iOS端包体积50M优化实践(二) 图片优化》 《百度APP iOS端包体积50M优化实践(三) 资源优化》 《百度APP iOS端包体积50M优化实践(四) 代码优化》 《百度APP iOS端包体积50M优化实践(五) HEIC图片和无用类优化实践》 二、方案调研 针对无用方法清理调研了各家厂商目前已公布的方案主流方案基于Mach-O LinkMap文件的分析但是主要存在以下问题 1.准确度低 2.针对系统方法需要手动过滤 3.针对load、initilize、attribute 相关调用无法识别 4.针对string反射调用无法识别Target-Action 注册Observer注册方法等无法识别 5.复杂语法场景下无法识别如继承链中的方法调用子类实现父类方法等场景 6.系统通知等场景 因为目前已公布方案存在如上不足同时因为下线代码敏感度非常高相关业务都很慎重。因此推动相关无用方法清理识别准确度将非常重要直接关系到相关业务下线无用代码的积极性因此弃用了上述方案。 三、方案选择 针对第二部分方案不足之处进行分析可以看到其准确度低的核心问题是针对产物进行分析拿不到所有需要的信息或者说还没有发现有效的手段去获取所期望获得的信息。而想要解决上面提到的问题最佳途径就是获取到尽可能多的代码信息。既然从产物回溯不到所需要的那么就可以考虑从源头也就是源码层面找到我们所需要的详细信息。 源码肯定包含了所有的信息但是针对源码如何分析呢主要有以下三种 通过脚本直接分析源码 需要匹配源码的所有语法规则才能够针对源码进行有效的分析相当于写一个源码解析器所以这个方案放弃 通过脚本直接分析AST抽象语法树 编译过程中产生的抽象语法树AST包含了需要的所有信息并且clang也提供了命令行使用该命令行能够直接获取到AST数据。但是clang 命令获取AST数据是以单个类为维度的类与类之间的关系很难获取到如继承关系分类和主类的关系是无法获取的所以这个方案同样放弃 通过libtooling 和 Swift Compiler自建编译套件分析AST Swift相关会在下一篇文章中介绍 既然通过clang命令生成的AST产物分析仍然不能满足需求那么直接介入编译过程从编译内部生成AST过程中获取需要的信息最终这个方案被采用。通过libtooling 和 Swift Compiler自建编译套件针对AST进行分析获取所需要的所有信息。 四、方案设计 如上所述百度APP最终采用了libtooling 和 Swift Compiler 静态分析方案那么下面就从原理和实现层面分别进行阐述。 4.1 编译流程简介 4.1.1 Xcode编译总体结构 本节先简单聊一下编译器的结构编译流程和静态分析是什么 △图 4-1 如图4-1 所示 LLVM 采用如上三段结构Three Phase Design分别是编译前端Frontend编译优化模块编译器后端Backend。那么这三段结构如何对应到Xcode呢如图4-2所示 △图 4-2 日常使用Xcode编译时Xcode调用了两个编译器前端分别为Clang 和 Swift通过两个编译器前端构建出通用的编译产物然后统一经过LLVM后端编译器进行目标文件生成。 通过Xcode的编译log可以看到针对Objective-CC C 使用了clang进行编译针对上述三种不同语言分别用不同编译参数控制 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang针对swift 文件则采用了swift编译器进行了编译 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend针对这两个可执行文件大家可以自行解包Xcode进行命令行调用也可以通过其 --help指令查看其支持哪些编译参数或者功能。Xcode 内部编译器实际上是苹果对LLVM 和 Swift 开源版本的定制化版本 和开源版本有一定的差异性。 4.1.2 Clang 和 Swift 编译流程 如下图所示Clang 和 Swift 前端编译流程可以看到Swift 编译处理流程多了SIL部分实际里面还有一个SIL Guaranteed Transformations当然SIL部分不是重点。从图4-3中可以看到Clang 和 Swift compiler 都会生成AST 且发现AST中包含了我们需要的绝大部分信息并且Clang 和 Swift Compiler 也暴露了相关获取AST信息的接口那么剩下的工作只有四点 1.搭建编译套件工程确保它正常run起来 2.获取AST并且根据Objective-C 或者 CC的语法特性获取所需要的数据 3.针对获取的数据进行业务分析处理 4.开源版本LLVM和Xcode实际使用版本具有一定差异性因此部分编译相关内容需要进行相关适配 △图 4-3 4.2 总体方案设计 针对一门程序语言的使用而言如图4-4所示包含两个层面一个层面是声明另一个层面是调用。声明类协议属性方法函数等等同时声明的内容是为了被使用所以同样声明的内容皆可调用只不过是内部调用还是公开调用问题。从技术角度而言声明的所有内容 减去 被调用的声明内容剩下的就是未被调用的内容也就是我们需要的 无用方法。当然技术层面的判别最终还是要进行业务判定因为有的属于基础能力对外提供至于是否要删除则需要进一步探讨。本文主要探讨技术层面问题。 △图 4-4 从clang源码中可以知道声明和调用分别对应LLVM源码中的基类Decl 和 Expr整体技术方案如下图 4-5所示针对无用方法分为处理分为四层 1.Basic 层组装编译工具所需的编译参数 进行语法规则匹配 2.Transformer层针对语法规则匹配数据进行转换转换通用型数据格式 3.通用数据层通过Transformer层产出的数据进行分类存储所存储数据包含了代码的所有数据如针对属性方法协议等数据均进行了分类存储 4.业务应用层针对通用数据层产出的存储数据进行业务分析即可 △图 4-5 4.3 详细方案实现 4.3.1 Objective-C 编译工具搭建 编译工具的呈现形式是一个类似Xcode自带clang的可执行文件如图4-6 红框所示内容。 /Users/UserName/Documents/XcodeEdition/Xcode14.2/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang△图 4-6 简单来说通过源码构建的编译工具具有Xcode clang 的部分功能利用其编译过程中产生的AST对象进行抽象语法树分析获取到所需要的编程语言的所有语法信息。 4.3.1.1 LLVM 源码构建 编译工具的搭建需要依赖LLVM提供的静态库或动态库这些库通过自己构建LLVM源码来获得。可以从github获取LLVM源码路径进入LLVM github界面后有可能会困惑需要构建哪个分支或者tag的代码呢哪个版本和Xcode使用的clang是对应的目前Xcode的版本是 14.2 或者 14.3 使用命令 clang --version 可以看到Xcode用到的是clang 14因此构建了release/14.x没有找到对应关系推理得出构建成功后执行构建的clang --version 会发现开源版本clang 和 Xcode的小版本号是不一样的这是因为Xcode 用的clang 苹果会基于开源代码进行定制这从Xcode中clang 的依赖库或头文件数量。另外从编译log也可以看到Xcode clang支持的部分参数开源clang是不支持的。尽管苹果有一些定制但是总体影响有限。因此也不必过于在意小版本号是否一致。初步验证了一下构建最新的release/16.x clang16 也可以。 △图 4-6 具体构建命令主要分两种一个是Ninja 构建方式一个是Xcode方式需要Xcode调试源码可以选择Xcode模式但是最终集成到编译工具中的静态库一定要构建成Release模式这样工具体积会降到最低一些警告类异常也会被屏蔽掉。可以参照LLVM 开源库中的start guide 构建过程进行构建其中涉及的组装命令可以自行拼接也可以用下面的命令 构建过程 git clone https://github.com/llvm/llvm-project.git cd llvm-project mkdir build 这个build文件夹可以自行命名不固定。针对不同目标可以创建不同文件夹进行不同构建如 mkdir ninjaBuild 或 mkdir xcodeBuild cd build or cd xcodeBuild cmake -G Ninja -DCMAKE_BUILD_TYPERelease ../llvm cmake --build .编译Xcode版本Ninja替换为Xcode即可。 4.3.1.2 工程搭建 LLVM提供了两种工具 libclang 和 libtooling百度APP采用的是 libtooling其异同点如下所示 libclang网络资料未实测 1.提供稳定的 C 接口具有遍历语法树获取 Token代码补全等能力。 2.接口稳定clang 版本更新对齐影响不大 3.libclang 不能获取到 AST 的所有信息 libtooling实测 1.提供 C 接口产出的工具不依赖于编译器可作为独立命令使用 2.接口不稳定AST 有升级需要更新相关依赖库 3.libtooling 可以获得 AST 的所有信息 最终选择 libtooling 形式核心原因就是 libtooling 可以获取 AST 的所有信息同时能够不依赖于Xcode 独立运行。工程的搭建本身并不复杂还是属于API 使用层面可以直接参照 libtooling的官方文档。 △图 4-6 总体代码流程如图 4-8所示主要核心点是五个部分 参数解析 创建 ClangTool 参照LLVM源码 ClangTooling - Tooling.h Line309 创建 ASTFrontendAction用于获取 AST 数据创建 ASTConsumer 和 进行 ASTMatcher 绑定 针对 ASTMatcher 匹配项进行各语法规则匹配 根据匹配数据进行数据过滤及业务处理 4.3.1.3 数据存储结构设计 数据存储结构采用 json 格式以下为基础数据格式示例可以根据实际需求拓展 objc(协议or类)类名(类方法or实例方法)方法名称:{ identifier:objc(协议or类)类名(类方法or实例方法)方法名称, isInstance:true, kind:16, location:{ col:36, filename:文件名称, line:147}, name:方法名称, paramters:参数, returnType:返回值类型, sourceCode:源码 }{declaration:{identifier:objc(协议or类)类名(类方法or实例方法)方法名称,isInstance:true,kind:16,location:{ col:列数,filename:声明所在类名, line:行数 },name:方法名称,paramters:参数名称,returnType:返回值类型,sourceCode:源代码 },kind:1,location:{col:5,filename:当前所在文件名,line:15 }}五、遇到的问题及解决方案 1. 属性调用识别问题 针对 Objective-C 的属性在编译后对应两个方法 get 和 set 一个是 ivar调用方有可能只调用 get 或者 set 或者 ivar所以当只发生一种调用时就算这个属性被调用当前属性不属于无用方法。需要在结果中把另外两个方法剥离。 2. 提取方法内容时同样需要对头文件进行提取 方法的实现不一定只在.m 文件中如C的头文件是可以进行方法实现的Objective-C 的.h 文件 通过 inline 实现一些方法在语法上也是可行的。所以进行方法提取时候关注实现文件同时也要关注头文件。 3. 针对继承问题 子类实现父类方法等场景在识别方法时全部回溯其父类以其父类名称作为 上文数据结构中 identifier 中类名部分这样所有的方法都可以和其声明类匹配。 4. 过滤系统方法调用 LLVM提供了接口判断当前方法是否属于系统类。 5. 过滤业务类实现系统方法问题 针对当前类中所有的方法均在当前类 和 回溯其继承链条中的父类 分别判断其是否属于系统方法如果属于系统方法则直接过滤掉。 6. 针对协议方法的实现目前还没有有效手段识别当前方案是直接过滤掉协议方法所有协议方法均视为已经调用 在提取方法时判断当前interface 遵循了哪些协议遍历协议中的方法判断其是否为协议方法是则标记为已调用。 7. 子类实现父类协议问题 回溯当前类的继承链条在继承链条中判断遍历其所遵循的协议判断其是否为协议方法。 8. 正常业务实现协议应该明确标注当前类遵循了协议 如 interface 但是实际场景中有很多代码在实现协议时并没有标注conformprotocol 这样就对协议方法的判断产生影响如 6.7方案均失效了 如果组件中少量这种问题当推动相关方修复此问题需要明确遵循协议。但是如果有的组件这种场景较多短期不会修复所有那么就需要进行临时性适配。针对这类组件收集其当前组件所声明的协议的所有协议方法用收集的协议方法和当前组件提取的所有声明做差集存在误伤的可能但结果是置信的组件只是一个维度也可以针对其关联组件进行相关处理因为有时他实现的组件不一定在当前组件内这就需要当前组件的依赖关系了。 无用方法case很多列举部分供大家参考。 六、总结 这项技术实际上在百度APP早已经应用因为笔者之前负责百度APP的接口变更审核组件完整性校验隐私合规调用链分析等均是依赖于此项技术无用方法识别只是笔者在做体积优化时想到的其功能的一个延展。当然如上描述的技术问题细节处理无用方法显然更细腻case更多。后续文章会针对Swift无用方法分析接口变更审核组件完整性校验隐私合规调用链分析等一一作出介绍。 ** ——END——** 参考资料 [1]libclanghttps://clang.llvm.org/doxygen/group__CINDEX.html [2]libtooling 官方文档https://clang.llvm.org/docs/LibTooling.html [3]LLVM源码https://github.com/llvm/llvm-project 推荐阅读 基于异常上线场景的实时拦截与问题分发策略 极致优化 SSD 并行读调度 AI文本创作在百度App发文的实践 DeeTune基于 eBPF 的百度网络框架设计与应用 百度自研高性能ANN检索引擎开源了
http://www.ho-use.cn/article/10819859.html

相关文章:

  • 手机网站被做跳转做的网站电脑上跟手机上不一样
  • 网站后台地址忘记了佛山市禅城网站建设公司
  • 甘肃住房与城乡建设厅网站如何打开国外网站
  • 宁波网站建设团队排名wordpress登录400错误
  • 新闻类的网站如何做优化、计算机基础网站建设和网络安全
  • 教育类网站怎么做下载四川天府健康二维码
  • 上海的做网站的公司学做家常菜的网站有哪些
  • 网站建设书生商友做餐饮培训网站广告
  • 英德住房和城乡建设部网站哪个装修公司比较好
  • 做电商网站用什么技术项目公司crm系统管理
  • 建设公众号网站如何成立网站
  • 城乡住房建设部网站建设银行 网站首页
  • 网站结构分析怎么做试用网建设网站
  • 南京做网站需要多少钱郑州网站推
  • 手机网站开源模板宁晋seo网站优化排名
  • 注册外贸网站有哪些问题网站icp备案新规
  • 现代教育网站开发项目的研究中山骏域网站建设
  • 面向搜索引擎网站建设灌南住房建设局网站
  • 如何看到网站的制作公司河南软件开发
  • 省级建设网站域名解析wordpress主页
  • 网站制作网站制作公司章丘营销型网站设计公司
  • 织梦做的网站图片路径在哪里微网站推广
  • 惠州网站设计哪家好seo网络营销外包公司
  • 保定做网站电话机械设备行业网站建设
  • 建网站非要做外链吗薪酬体系搭建工具
  • 做网站难吗_挣钱吗东莞东坑网站设计
  • 建站小程序快速上线你们公司的网站都备案了吗
  • 建设的基本流程网站怎么做网页赚取点击率从而赚钱
  • 深圳网站制作网站建设零基础网站制作视频教程
  • 用什么网站可以做电子书设计网页代码源代码