范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

支付宝App瘦身新思路重复指令合并技术

  前言
  稳定性、性能、包大小,是保障移动端用户体验的三驾马车,是app承载业务获得稳定、高效、低成本、增长的重要基石。其中包大小对下载转化率、降低拉新拉活成本等方面的影响至关重要,这在业界已经成为共识,近年来头部app针对下沉市场的极小包策略,更是将包大小的价值提升到了极致。但在实际开发过程中,随着功能的不断迭代,App体积越来越大不进行管控的话会直接影响安装转化率,因此App包大小需要持续的管控和优化。 现状
  目前支付宝已经有不少关于安装包瘦身的方案,如:代码治理、资源治理、业务治理、构建优化,经过几轮治理之后现有手段让App瘦身效果越来越不明显,因此需要一种新的手段来进行App进行瘦身来突破的目前的瓶颈。 新方案
  新的App瘦身方案是从App的可执行文件开展的,在二进制指令层面进行优化,通过合并大量的重复指令来实现二进制文件体积的减小,从而实现对安装包的瘦身。
  iOS重复指令合并优化成果:
  架构:arm64
  本次共优化了的bundle占比是62%,优化后iOS二进制文件减少16.6MB。全量优化后预计能够减少20MB以上。 瘦身原理
  下图中最左侧是源代码,中间部分是源代码对应的汇编代码,最右边是源代码进行重复指令合并后的汇编代码。
  从上图中的操作是将重复的指令片段提取到公共的区域中,原来的重复指令段被替换为跳转指令,实现总指令数目变少。不难看出优化后的指令中长度变短了,这也就意味着指令所占用的空间减少,从而实现了二进制文件的瘦身。 技术架构图
  本方案架构分为两部分,编译构建和环境适配。编译构建部分主要是解决重复指令合并的编译问题,用来产出经过重复指令合并的App安装包;环境适配主要是重复指令合并的配套设施建设,如crash堆栈的还原、调试信息的还原、产物一致性的校验。
  工程包构建工具链:主要负责根据基线从git仓库中拉取工程代码,并使用APKit构建编译环境;环境准备好后Xcodebuild会根据工程中的配置文件生成编译命令,具体的编译命令由Apple Clang来执行并生成IR文件(用于编译优化)以及.frameowork文件(用于正常包);完成编译后LinkLibChecker会根据工程配置提取工程依赖的二进制lib文件;最后将framework和IR和依赖的二进制lib上报到OSS和基线中。
  编译优化安装包构建工具链:RIMKit根据基线下载需要优化bundle的IR文件、不参与优化的framework文件、依赖的二进制lib文件;AlipayRIMOpt工具会将对个IR文件进行合并优化产出libportalOpt.a文件;APKit工具负责构建安装包的编译环境;RIMLinkFlagsUtil工具负责调整portal工程的链接参数,将参与优化的bundle从中链接参数中剔除,把libisaopt.a和依赖的二进制lib添加到链接参数中;最后由Xcodebuild会根据portal工程的配置打安装包。
  环境适配的工具链:一致性校验主要负责检查优化后的安装包中资源文件、符号等信息是不是比正常包的有缺失;crash堆栈还原主要是负责在优化时给新添加的符号及其指令增加调试信息,方便后续的符号定位。反解堆栈时将新增的符号导致堆栈的变换还原为正常未优化时的堆栈状态;debug堆栈还原主要是解决编译优化包线下调试的问题。 难点突破重复指令的识别
  要想合并重复指令第一步必须先找出重复的指令,但对于支付宝这种量级的App而言其指令的数量在亿级,在这个数量级下想要快速找出重复的指令并不是一件容易的事情。必须采取合适的策略才能高效解决该问题,接下来为大家介绍求解的具体策略。
  重复指令的定义:两条机器指令的汇编指令、寄存器、立即数所组成的数据须完全一致才认为是重复的指令。
  明确重复指令的定义后,对指令进行编号,结果如下图所示:
  按照上图所示的编排方式,可以把每一行的指令看成字母,这些指令对应的编号就组成了两个字符串:
  funcA:ABCDEFGHIKMNOPQR&(&表示终结符)
  funcB:ABCDEFGHJLMNOPQR$($表示终结符)
  寻找重复指令需求就变成了寻找该字符串中的公共子串。这里考虑使用后缀树来解决公共子串问题,后缀树是一种能够快速处理各类字符串问题的数据结构,非常适合应用在这个场景中。
  下图将字符串
  ABCDEFGHIKMNOPQR&ABCDEFGHJLMNOPQR$构建成为后缀树的形式。接下来介绍如何通过后缀树找到重复的字符串。
  针对上图中的后缀树做一个简单的介绍,0号表示根节点,方形框表示叶子节点,圆性框表示中间节点。以三号节点为例:3号节点是21号和22号节点的父节点,这表示ABCDEFGH是字符串
  ABCDEFGHIKMNOPQR&ABCDEFGHJLMNOPQR$和
  ABCDEFGHJLMNOPQR$的公共子串。所以子节点数量表示了父节点字符串出现重复的次数。因此在提取公共字符串的时候可以忽略所有的叶子节点(方形),因为他们的子串数目为零表示没有出现重复的情况。
  分析后缀树的非叶子节点发现4、5、6、7、8、9、10号节点代表的字符串为3号节点代表的字符串的子串;16、17、18、19、20号节点为15号节点的子串。因此只需要将3号15号节点填入下面的表格中。
  可合并字符串计算表格:
  原始字符串
  ABCDEFGHIKMNOPQR&ABCDEFGHJLMNOPQR$
  节点编号
  3
  15
  公共字符串   ABCDEFGH   MNOPQR   子节点数S   2
  2
  正因为采取了后缀树算法,让发现重复指令的效率从朴素算法的O(n^3)降低为O( n )。目前优化支付宝300+的bundle的重复指令查找耗时控制在13分钟左右,让重复指令合并能够顺利迈出第一步。 剔除不能合并的指令   并不是所有指令都能进行合并的比如:跟LR寄存器有关的操作。这些相关的指令合并后会导致程序进入死循环。所以这里面临的第二个难点是把不能合并的指令找出并剔除。   上图中funcA和funcB函数的开头和结尾的两条指令是用来做压栈和出栈操作的都是跟LR和FP寄存器相关的,所以这几条指令是不进行合并的。在求解重复字符串的时候要进行剔除操作如下图所示。   了解了不可合并字符串的剔除规则后,接下来介绍如何根据后缀树找出的重复字符串求解出待合并的字符串集合。根据不可合并字符串的剔除规则可以将3号节点和6号节点的字符串分割为下表待合并字符串这一行的形式。   可合并字符串计算表格:   节点编号   3
  15
  公共字符串   ABCDEFGH   MNOPQR   子节点数S   2
  2
  包含的无法合并字符串   C   M   O   待合并字符串   AB   DEFGH   N   PQR   通过上述策略可以有效的剔除不能参与合并的指令避免程序出现异常,同时又可以将重复指令尽可能多得进行合并,如果将存在不能合并的指令序列完全放弃掉合并效果会大幅缩水。 部分指令不能合并的原因分析   关于LR寄存器:程序跳转(BL指令)时,会将BL指令后面的指令地址写入LR寄存器中,当程序执行完成后便会回到LR寄存器指向的地址。   场景一:压栈和出栈   上图中假设发生重复的指令片段在压栈和出栈这两段指令上。当程序执行完1号红色箭头时LR寄存器中原有的数据从指向main函数中的某个指令地址被替换为指向E行指令的地址。接下来要执行到2号红色箭头时需要构造funcA的栈帧,但LR寄存器中的地址不再指向原本要返回的main方法中,而是指向了funcA中的E行指令的地址这就导致程序再也无法返回到main函数中继续执行,所以这种合并会导致程序出错。   上图中1号黄色箭头执行完后并不会改变LR寄存器也不需要返回。当2号黄色箭头执行完时,LR寄存器里的数据是指向要返回的main方法中的某条指令,执行ret后即可正常返回,但是带来的副作用是堆栈显示存在异常。异常结果如下图所示:   merge1执行完成后应该出栈,但结果确实funcA出了栈。所以这种情况也不能进行重复指令的合并操作。(如果1号黄色箭头指向的不是b指令跳转而是BL指令跳转,则同样会导致程序返回异常)。 场景二:分支指令   上图中假设发生重复的指令片段在函数调用这段指令上,存在调用关系main->funcA。当程序执行完1号红色箭头时LR寄存器存储了E指令的地址。接下来要执行完2号红色箭头时LR寄存器存储了D指令的地址。但是由于在merge0函数中没有构造栈帧所以LR中原来指向E指令的数据被覆盖掉了,永远指向了D行的指令导致merge0无法返回到funcA中,程序也就无法正常执行。因此涉及到BL分支指令也不能进行合并。 重复指令的合并   找到待合并字符串后,并不意味着都可以进行合并,因为有些字符串合并后反而会变的更长。所以需要预先估计每个待合并字符串的收益,收益大于0才会进行合并。接下来推导一下重复字符串合并所节省的字符数量公式:   L:公共字符串长度(重复指令数量);   S:子节点个数量(重复次数);   R:节省的字符数量(节省出的指令数量)。   节省字符数量的公式:   添加指令为BL时:R = L*(S-1) - (S*1+1)   添加指令为B时:R = L*(S-1) - (S*1) (被合并的指令是以ret结尾的时候使用B指令跳转)   L*(S-1) 表示:S个长度为L的字符串的长度之和-公共方法中字符的个数。   (S*1+1) 表示:S个重复字符串乘以新增加的字符数(bl指令)+合并后的公共方法中新增加的一个L字符(ret指令),如果是B指令则不增加L字符(ret指令)。   接下来继续完善重复指令算表格。   可合并字符串计算表格:   原始字符串   ABCDEFGHIKMNOPQR&ABCDEFGHJLMNOPQR$   节点编号   3
  15
  公共字符串   ABCDEFGH   MNOPQR   子节点数S   2
  2
  无法合并字符串   C   M   O   待合并字符串   AB   DEFGH   N   PQR   待合并字符串长度L   2
  5
  1
  3
  预计节省字符数R   -1   2
  -2   1
  可合并字符串   无   DEFGH   无   PQR   可合并字符串位置坐标   无 [4,8]   [21,25]   无 [14,16]   [31,33]   利用上文中提到的预计节省字符数的计算公式算出每个节点预计节省的字符数,接下来将预计节省字符数小于1的节点删除,因此可合并字符串只剩下EFGH和PQR。   确定待合并字符串后,可以开始进行重复指令的合并操作,具体步骤如下图所示:   第一步:根据待合并字符串找出其对应的指令,并在程序原有的指令中插入一个新的函数_ALIPAY_REPEAT_FUNCTION_1。并将字符串的所对应的指令填入该函数中,然后再向指令结尾添加ret指令。   第二步:根据待合并字符串中的位置坐标,找到在原程序中的位置。   第三步:并将该位置原有的指令替换为 bl _ALIPAY_REPEAT_FUNCTION_1指令(如果被合并的指令是以ret结尾,则可以使用B指令进行跳转),从而实现对重复指令的替换,至此便实现了重复指令的合并优化。 适配新的编译流程   为了能够发现并且尽可能多的合并重复指令,需要改造当前的编译工具链流程。将多个传统单个编译单元中的指令合并到一个更大的编译单元中,具体流程如下所示。   非重复指令合并的编译流程:   非编译优化的编译流程是将一个文件作为一个编译单元进行编译,产生.o文件后由链接器链接为lib库文件,lib文件最后被链接器链接到可执行程序中完成可执行程序的编译流程。如果按照这个流程进行重复指令合并优化,那么只能将这个一个文件中重复的指令进行合并,能够合并的指令数量有限优化后效果不佳。为了能够将更多的重复指令合并,需要对传统的编译流程做出调整。   适配重复指令合并的编译流程:   适配编译优化后的流程是将单个文件编译为IR中间文件,由llvm-link将其链接为一个IR文件,之后进行常规优化。接着进行重复指令的合并,由于之前将多个编译单元合并为一个编译单元,在做重复指令合并的时候就可以将多个文件里的重复指令进行合并,实现最大化的优化效果。重复指令优化产生.o文件。最后obj文件被链接器链接到二进制可执行文件中,至此编译流程结束。   将编译流程配合重复指令优化进行调整后相比较于调整前App体积减少了接近8倍。 对App性能的影响   指令合并优化目前只是新增了BL和B指令,并没有真正的去构建函数栈帧,所以不会增加内存的额外开销。通过对启动性能的分析评估,影响在约为0.8ms左右。   作者:松茸   来源:微信公众号:蚂蚁质量AnTest   出处:https://mp.weixin.qq.com/s/whGWV_m4CfcHjamiVuxSUw

灵丘觉山寺,北魏遗风藏身山水圣境古人曾曰觉山山空月明时,岩际尝闻棋子剥啄声或笑语,至夜分不息。土人以为飞仙往来也。觉山真是静谧,静得使人感到它和1500余年前的显赫际遇有些不协调。觉山寺位于大同市灵丘县城东南15一个公园里留了一块荒地,于是来了5种猛禽眼看着秋风渐起,我去了趟通州的绿心公园。每年冬季我都在通州寻找长耳鸮,去年它们便从运河森林公园搬家来到了绿心,于是我也来这边观察它们。这种体型中等的猫头鹰是一种比较能够适应人类环境Samskip重磅新线杜伊斯堡罗斯托克Samskip公司与Hector铁路公司合作,在罗斯托克港和杜伊斯堡之间推出了新的联运服务。新的线路将与波罗的海海港和斯堪的纳维亚半岛之间的滚装服务连接,每周运行三天。Hector两年内狂跌4。7万亿!腾讯帝国究竟是如何一步步走到如今的?头条创作挑战赛导读截止到10月18日,腾讯股票收盘价为254。4港元,市值2。44万亿,而在一年前2021年的2月时候,腾讯的股价最高达到了峰值749港币,市值7。2万亿。短短一年精美朋友圈配图,拿去发个朋友圈,看看有多少赞1我要用尽我的万种风情,让他在没有我的每一个日子里不得安宁!2如果你可以把你的人生当作是这个游乐场,那你以后就算跌倒了,都不会哭!3你若坚持,定会发光。因为时间是所向披靡的武器,它时代使命时代赋与我们这代人的使命知道是什么吗?铁(路)公(路)机(场)已完成城市化建设已尾声(拐点)互联网5G已普及商品已饱和过剩一边人民无力消费还有物流业已配齐接下来是脚趾头能想到智能社振兴实体的9。5万亿,你的春天真的来了么?有网友说电商不倒,实体难搞,我看未必。实体经济受电商经济冲击不假,但并不全是电商经济造成的,电商经济也从来没有脱离实体经济,电商经济的根还是在实体经济的基础之上的,两个原因造成部分地平线投靠大众资本盛宴还是全新的路径最近,大众汽车集团和地平线同时宣布,大众汽车旗下的软件公司CARIAD将与地平线在中国成立一家合资企业,股权比例为64。关于投资的具体细节,大众汽车集团(中国)有限公司董事长兼首席销量三连跌产量七连降,邓智涛能让长安马自达重回正轨吗?虽然都说不破不立,但邓智涛从王辉手中接过的这个烂摊子,实在是过于惨不忍睹了。9月底10月初,长安汽车两则公告引起了人们的注意。首先是任命原长安马自达执行副总裁党委书记王辉为长安汽车中车四方法治建设不可或缺文法人杂志全媒体记者姚瑶资料图片中车青岛四方机车车辆股份有限公司(下称中车四方)作为中国高速列车产业化的主要制造基地之一,在高速列车的产业发展上起着关键作用。9月27日,法人记者围中国人专坑中国人?4万人被遣返,围猎生意要黄了作者猫哥来源大猫财经未来几个月内,将有4万人被遣返回中国。为啥呢?菲律宾方面终于下定决心,开始要打击臭名昭著的离岸网络博彩,最近他们决定要关闭175家被吊销执照但仍非法运营的离岸网
美联储加息即将结束,缩表加速意味着什么?8月初在佩洛西落地,要变天了这篇文章里我说美股很快要大跌了,果不其然,之后美股又反弹了一个多礼拜之后就见顶了,一众华尔街资本家也在那段时间借机出货给了去美国避险的资金。马斯克确实是重回战略视野!四大险企银保渠道上半年均现两位数增长,花式出招大手笔招揽记者苗艺伟今年以来,面对代理人渠道业绩的持续下滑,头部险企开启新一轮对银行渠道的奔赴。据界面新闻记者统计,今年上半年,多家上市险企银保渠道保持了两位数增长,且通过各类模式大手笔招揽中企举办印尼制造业投资峰会获热烈响应中新社雅加达8月31日电(记者林永传)31日,一场由中资企业在雅加达举办的制造业投资峰会,获印尼经济界热烈响应。来自印尼全国70多家工业园区600多家企业的900多名代表与会。印尼商务部支持新能源车企出海,上汽科技赋能成为出海擎旗者近年来,全球新能源汽车产业蓬勃发展,中国新能源汽车领跑全球,并借助这一先发优势走出国门。为持续提升我国新能源汽车产业国际竞争力,商务部近日为新能源汽车的出海之路再次送出助攻。近日,油价调整消息油价下调!9月8日国内加油站汽柴油调后新零售价油价调整消息油价下调!9月8日国内加油站汽柴油调后最新零售价今天是2022年9月8日,星期三!本周的第3个工作日,油价方面迎来利好消息,国际油价开始下跌,新一轮国内成品油或将开启下凄惨!毛宁一大把年纪,混到来商场演出,被女粉丝拉着拍照提起昔日情歌王子毛宁,在上世纪九十年代是家喻户晓的明星。论颜值,论唱功都秒杀现在的小鲜肉。就这么一位被万人追捧的大明星,老来也凄惨。日前,被人拍到53岁高龄的毛宁在郑州某商业中心演宋喆疑似提前出狱?王宝强紧急加强安保,马蓉投资1500万将去澳洲在马蓉出轨时隔6年后,宋喆也又有了消息,多家媒体突然开始报道,宋喆因为在自己服刑期间,积极听从管教安排,在监狱中表现得很好,所以疑似获得了减刑,将要在下月提前出狱。与此同时,马蓉那7位演技炸裂的女配角,施诗让人印象深刻,杨蓉让女主黯然失色众所周知,在一部影视剧中,往往可以见到配角比主角演技更好的一幕,几乎可以说司空见惯。有些女星天生没有主角命,于是乎,场面只能以配角的身份出现,而有些女星顶着女主角的光环,演技方面却小沈龙离开老赵太落魄,工地搬水泥赚钱,扬言再苦再累也不回去01。hr近日,小沈龙在工地搬水泥赚钱一事引发了不少网友热议!02。hr小沈龙,原名戴小龙,1990年3月出生于黑龙江省大庆市,18岁模仿小沈阳闯进北京。2009年,参加中央电视台张天爱不仅仅是长得漂亮,对付渣男徐开聘的操作也是非常亮眼娱乐圈近两年来拍的影视作品虽然少有什么非常好的作品,但是娱乐圈的人们确实一刻都不安生,一个一个大瓜都是又保熟又保鲜的,最近我们漂亮的女神张天爱又教了我们一招渣男的办法,直接公布渣男他是张柏芝第1任男友,拍古惑仔被孤立挤兑,现在成了个诗人古惑仔系列,是无数8090后的青春回忆。其中所呈现的一个个热血江湖兄弟情谊,感染了许多人。虽然只是电影,却引起了很多人的效仿,认为这就是真正的江湖。古惑仔系列电影,曾经风靡香港大陆