当前位置: 首页 > 网络应用技术

女性击败Dancecc工具链系列快速调试性能优化方案

时间:2023-03-08 13:48:56 网络应用技术

  Dancecc(Dance Compiler Collection)是客户基础设施下的编译工具链品牌。Clang/Swift编译器,Linkor,LLDB调试器和LLVM/Swift Projects of LLVM/Swift项目和优化方案中的LLVM/Swift Projects的语言基本库,涵盖了构建性能优化和应用程序性能稳定性优化,本系列将重点放在这些场景上。优化的情况,介绍了字节中编译工具链技术的优化方案和实施。

  一般来说,大型Swift项目通常包含大量OBJC/C/C ++甚至Rust),包含100多个Swift模块,并且可能同时包括二进制零件和源代码。在当前的Xcode 13体验下非常糟糕。它通常存在类似于诸如“断点陷入菊花之后”和“显示变量故障”等问题。它始终存在于多个历史Xcode版本中。

  图1:Xcode变量区域图形阶层变成chrysanthemum,使用Xcode 13.3进行测试和下面提到的重新出现的演示

  苹果团队的这一部分延迟的原因是Apple的内部项目与外部项目开发模型之间的巨大差异。Apple的内部产品(例如系统应用程序,系统库)将直接嵌入iOS固件中,并直接从Dyld共享中受益缓存(请参阅WWDC 2017-APP启动时间:过去,现在和未来[1])以改善加载加速丝,这意味着它们通常分为薄的主二进制,配备了相当大的动态链接库(动态框架)和插头-在。

  例如,我们使用iOS消息应用程序(MobilesMs.App)作为iOS 15.4模拟器测试测试的示例。可以看到,总共22个动态链接已经看到了22个动态链接库,其中9个是非公共的。其中大多数是支持消息应用程序的功能库。这些图书馆占据了大量存储空间。

  图2:消息应用程序的动态链接库列表

  为了追求更快的冷启动时间,iOS平台的第三党开发人员的项目,因为没有对Dyld共享缓存的优化(Dyld 3提出的启动 - UP闭合只能针对非cold进行优化开始),许多项目将尽可能少地与可能的链接库一起使用。此外,由Cocoapods,Carthage,Swift,SwiftPM和其他包装经理在开源社区中的普及而引起的Swift模块爆炸增长,滥用PRE PRE-Binary Framework/XCFREWORK以及封闭源公司的SDK的集成,最终形成了一个卷的体积。还包括符号的主要二进制文件和较长的搜索路径。

  以公司的内部测试应用程序的内部测试版本为例,在使用调试,OnOne模式,不剥离(剥离)任何符号的情况下,您可以看到其主二进制的大小为1.1GB,并且动态链接库的数量为105,但仅包含Apple的系统库和Swift Standard库。企业码与静态链接库集成。

  图3:公司的飞行图书应用程序的动态链接库列表

  这两种不同的工程结构在调试经验上带来了非常显着的差异,苹果的Xcode团队和调试器团队近年来已经进行了优化。工程结构。

  PS:从理论上讲,通过业务工程结构的转换,在本地开发模式下,使用动态链接库包装基本静态链接库以减少主二进制的大小随后的矮人搜索的时间消耗),但是大型项目促进工程结构的转型将是一个很长的过程。

  图4:降低主二进制规模的项目设计

  经过调查,我们发现行业中的共同做法无非是这些想法:

  我们致力于在Byte Beating的移动终端提供基本能力支持,因此我们提出了一套不依赖业务工程结构转换的解决方案。相反,我们从LLDB工具链开始,以提供有针对性的调试性能优化。

  在调查过程中,还可以确定,借助自定义LLDB工具链(包括iPhone Simulator,Real Machine和Mac应用程序),将其集成到Xcode IDE是完全可行的。

  图5:自定义LLDB工具链的文件结构。一系列以下文章将分别解释。

  LLVM/LLDB本身的工具链代码位于Apple的开源类别(仓库地址:https://github.com/apple/llvm-project)-MAY上,请确保工具链代码和功能的一致性。

  在稍后提到的一系列优化方法之后,根据公司的大规模项目飞行书测试,编译器采用SWIFT 5.6,Xcode选择13.3作为比较调试性能的示例:

  v消费者2分40秒。PO需要1分5秒P需要20秒和5秒。6:切换自定义LLDB工具链

  图7:辩论优化演示,使用Xcode 13.3自定义LLDB,以及操作文本中提到的时间 - 耗时的演示(原始PO大约需要1分钟):

  在介绍我们自定义LLDB工具链的优化之前,首先简要描述LLDB核心调试场景的工作流程,以促进技术优化点的关注。

  我们第一阶段的目的是主要优化核心调试方案,包括最常见的“断点落入Xcode的左变量区域”(v),“单击显示描述”(PO)(PO),“检查显示类型” P)。

  图8:LLDB的互动命令

  苹果在WWDC 2019-LLDB中进行了更详细的介绍:超越“ PO” [2]。在这里,我们进一步详细说明了它的一些工作流程,并提供了后面文章中特定优化技术点的参考。建议与视频一起学习。

  PO是命令的命令

  图9:PO流程

  p是命令的命令

  图10:P的过程

  相比之下,PO和P之间的最大差异是表达式执行的结果,如何获得变量的描述。PO将直接显示操作说明获得的字符串(支持CustomDebugString Convertible [4]协议)运行时。它并不真正了解对象的细节。

  图11:获取对象描述的实现详细信息

  P使用SWIFT运行时(OBJC是ISA,方法列表,并且不描述信息),并且获得对象详细信息(支持可自定义反射[5]协议)并按层打印。依赖远程远处(必需的源代码,SwiftModule)或反射(不一定是用剥离),这意味着它是强限制的。版本(请记住这一点)。它不像OBJC那样成熟和稳定,您可以动态地了解对象的任何细节,而无需依靠编译器。

  图12:Swift动态类型的实现

  v是命令的别名

  图13:V的过程

  v的特征是整个过程中没有代码中的代码,也就是说,它没有理论的副作用。支持功能调用,不是真正的C ++/C/OC/Swift语法。

  根据发布日期(优化想法也适用于Swift 5.5),所有SWIFT 5.6的描述以解释优化方案。尚未排除Apple或LLVM上游进行其他优化替换,该优化替换具有一定的时间限制。

  喜欢迅速远程镜像遥控AST

  上面介绍了Remoteast和Swift Mirror的概念,不同的解决方案将影响Swift动态类型解决方案的性能。

  在测量之后,在闭合之后,在内部项目的复杂情况下,断点是从最初的2分20秒到1分钟的时间来耗尽的。现在,开关的一部分是通过lldbinit在多个项目中设置的[6]由Xcode自定义的文件。

  注意:与苹果同事进行了交流后,Swift型型型型系统是该团队提出的新解决方案已有20年了。目前,存在一些已知的性能问题,但是它与Swift变量和类型具有更好的兼容性。结束后,它将导致Typealias变量在P/V时以不同的方式显示出不同的显示。建议恢复国家。

  简要说明:LLDB假设所有框架包装格式都是动态链接库,而忽略了静态链接库的可能性。

  在调试测试项目中,我们遵循日志,发现LLDB将尝试使用dlopen加载静态链接库(静态框架)。显示(下面提到的演示的复制品):

  查看代码读取发现,此处触发的时序是,在LLDB执行Swift变量动态类型解析之前,由于需要激活远距离,因此需要将与源代码相对应的SwiftModule加载到内存。

  SwiftModule是一个包含AST的LLVM比特码[7]的编译器。出现在Swift代码中还将记录加载模块依赖项。主要二进制文件将记录汇编过程中所有串扰的收件人依赖项。

  当LLDB依靠加载模块时,当前模块名称会根据编译器获得的搜索路径缝制,然后将DLOPEN遍历。浏览高空开销:n模块,m搜索路径,复杂性o(nxm)(nxm)(nxm)(nxm)(nxm)(NXM)(NXM)(NXM)(NXM)(NXM)(NXM)(内部项目为400x1000级)。在执行之前,尚未检测到当前加载路径是否真的是动态链接库,并且最终生成了此错误开销。

  我们的维修计划是文件签名的文件判断,并且在动态链接库上仅执行DLOPEN。在内部工程测试(约1,000个框架搜索路径,400模块)的情况下,可以减少大约1分钟的跌落。

  仓库地址:https://github.com/president810/slowdebugtest

  该演示构建了100个Swift静态框架,每个模块都有100个编译单元来模拟复杂的场景。

  后来的一些测试数据优化将反复提及此演示比较。

  这些符号注定是为了记忆当前调试过程。

  PR:https://github.com/apple/llvm-project/project/pull/4077预计将上升5.7

  调试Swift代码时,从矮人重建Clong模块依赖性

  此开关的作用是,当Swift编译器遇到要导入Swift的Clang类型(例如C/C ++/OBJC)时,允许它通过自定义代理实现从矮人实现类型信息,而不是使用Clang Precoming模块[8]在编译器的帮助下,即PCM和clangimporter,以导入桥梁类型。

  切换后,某些叮当型类型的分析可能不准确(例如,Apple System库的覆盖框架,覆盖与本机Swift类型的同名类型C),但是它可以稍微加速分析速度,因为Clang clangPCM和矮人的分析。

  禁用后,内部项目的测试项目中的某些方案有了积极的改善,约10秒钟。如果您遇到问题,建议保持默认为真。

  在混合项目中,Swift模块依赖于C/OC clang模块很常见。在这种情况下,LLDB需要同时使用编译器,将其加载到相应的Clang模块到存储器,然后使用C/OC输入Swift类型的导入逻辑。

  但是在实际情况下,我们可能会有一些快速混合产品,这些产品是预先制作的产品,在非电流机中编译。在这种情况下,编译器记录的外部模块的路径很可能找不到当前机器。

  LLDB的原始逻辑将由4个对象文件插头-in(支持不同的二进制格式)来判断,以便每种可能的路径。每个可能的路径读取并通过文件io读取并分析标题。这是非常大的费用。

  我们内部采用的策略相对积极。除了使用FSTAT直接使用FSTAT进行前判断(而不是将其处理为4个对象插头-In,判断4次),还进行了MAC机器的一些特殊路径匹配规则。exexample:

  例如,Mac计算机的编译产品的绝对路径必须是开始,因此我们可以尝试获取当前的调试过程(非常快,LLDB过程不会更改)。如果生成了当前的设备,则直接跳过。

  图14:避免存在文件IO判断的特殊匹配规则

  通过这种优化,在内部项目的测试(超过1,000个外部模块路径,800多个无效的路径)下,第一个变量表明V大约需要30秒。

  当我们将内部项目用于性能配置文件时,我们发现和功能性呼叫消耗是主要的大头。该功能的功能是找到是否通过矮人(记录在马赫-O结构中)。时间 - 耗费主要是分析一次性矮人和每个搜索的部分遍历。

  LLDB本身具有用于缓存的参数,但问题在于,该缓存不存在于全局共享池中,而是在每个特定呼叫的临时堆栈中存在。呼叫方在呼叫结束时,该缓存将直接丢弃。

  图15:符号缓存参数

  在这里,我们引入了共享符号缓存,该缓存保留了此访问记录,以避免多个不同的卡路里仍在寻找相同的符号以更改空间的时间。实现计划相对简单。

  内部工程测量,第一个访问开销可以减少10-20秒,每个符号缓存均占BYTE的8KB,并且在一个调试周期中占据了800MB的大约100,000个符号。还提供了关闭开关。

  另一个优化和函数开销是,原始两个函数将返回所有匹配列表,因为C ++/Rust/Swift和其他支持的语言学将使用。变体的不同类型。这些符号名称将在矮人中记录,并在矮人中记录,同一删除相同的删除姓名。

  但是,呼叫者可能会关心同名的特定变体(甚至包括const或non -const),甚至许多地方也只有第一个符号。搜索所有符号文件实际上是浪费(在Swift 5.6版本中,累积10个呼叫,仅接一个第一个))

  我们为上述内容提供了一个新参数,并为预先过滤所需的特定类型提供了一个新参数。与许多语言标准库相似,提供了排序函数中的停止参数。这样,如果您只需要找到第一个符号,您可以提前终止搜索,并且完整的符号列表不受影响。

  图16:符号找到筛选参数

  在优化内部项目测试之后,它可以减少Swift类型中的C ++/C/OC类型,该类型需要大约5-10秒才能找到耗时的时间。

  在实际的项目测试中,我们发现动态类型的解决方案具有一些特殊情况,可以针对有针对性的快捷方式进行优化以消除统一的费用。这一优化的一部分仅对特定代码方案有效,并且不是普遍的。在这里列出

  核心基础类型(稍后转介给CF类型),这是Apple的许多基础系统库的支持。OBJC的许多类型的OBJC基础NS前缀也会为CF Type提供免费的桥梁[9]。SwiftsSwifts也支持一些Briding的Briding。常用的CF类型。

  CF类型的特征是其内存布局类似于OBJC的类ISA,但它不是真正的OBJC类或迅速导入的类型。ISA是固定的。

  目前,LLDB遇到出现在Swift堆栈中的CF类型,并且仍然将其用作标准叮当类型来执行C ++/C的分析。它还将找到父母ivar,这是更多的时间-Concuming。我们可以使用此功能提前判断并跳过无用的父级。

  图17:过滤器CF类型

  该优化可以在10-20秒的动态类型分辨率上进行优化10-20秒。

  未来我们将有一系列相关主题,包括:

  此外,本文中提到的非限制优化和功能将向Apple或LLVM上游提交补丁以退还社区。

  本文解释了如何通过开关和自定义LLDB进行大型Swift项目,以优化Swift Development学生的调试速度并提高整体R&D效力。它解释了LLDB的工作流程的一部分,以及优化的技术细节和实践效果。

  我们的优化目标不仅是服务于直觉的移动终端,而且还希望促进行业迅速和LLVM汇合的领域的发展,以在工具链的方向上交换更多的优化和构建。

  得益于Flying Book Basic Technology团队提供的一系列技术支持,以及最终的业务飞行员的帮助。感谢Apple同事Adrian Prantl对Github的沟通和反馈以及电子邮件,以协助定位。

  客户基础设施团队是一支由大型前端基本技术组成的全球研发团队(在北京,上海,杭州,杭州,深圳,广州,新加坡,新加坡和美国拥有研发团队。提高公司整个产品线的性能,稳定性和工程效率的基础架构;所支持的产品包括但不限于Douyin,当今的头条新闻,西瓜视频,飞行书籍,瓜瓜龙等,桌面和其他终端都具有 -深度研究。

  我们是客户型企业部门下的编译器工具链团队。团队成员由编译器专家和构建系统专家组成。我们的开源LLVM/SWIFT项目提供-Depth自定义的clang/Swift编译器,接头,LLDBTools和优化方案,例如调试器和语言基本库,涵盖了性能优化和应用程序性能稳定性优化的构建,并在效率方面实现了重大影响以及业务研究和开发的应用质量。同时,在实践过程中,我们也看到了许多令人兴奋的新机会。我希望有更多有兴趣编译工具链技术的学生会加入我们的探索。

  工作场所

  深圳,北京

  职位描述

  工作要求

  位置链接

  https://job.toutiao.com/s/fbs9clk