当前位置: 首页 > 科技观察

在处理棘手的bug时,新手和高手的差距在哪里?

时间:2023-03-15 00:32:07 科技观察

问题描述:从上周开始,团队中的一些iOS开发人员抱怨电脑特别卡。细心的同学发现,由于Xcode占用内存6-7G左右,而有的mac只有8G内存,内存满了导致卡顿。还有一些同学的mac内存是16G的,比如我(嘲讽脸),因为内存够用,感觉不卡。但是这个问题影响了团队的开发效率,所以需要解决。内存对比:洗澡、更衣、烧香、杀进程、清缓存后,分别拉取相邻的812版本代码和816版本代码编译,得出结论:816占用2G内存经过调试,使用了6.8G内存。:对于这个数据,我们心里是拒绝接受的。有两个抱怨如下:如果代码乱分配内存,那么内存爆出的应该是模拟器或者真机。它不应该是Xcode。如果当前版本增加10万行代码(实际少于),总代码量增加不超过10%,Xcode内存怎么翻倍。所以我们认为这一定是Apple的罪魁祸首,我们不怪,但不管是谁的责任,一定是代码或配置触发的,继续分析。分析方法的选择:摆在我们面前的分析方法有2种:查找代码:通过二分法编译不同日期的版本,找到导致问题的commit,确定是哪个变化引起的查找内存:分析增加的内存是什么,根据增加的内容分析问题出在哪里。如果使用方法1,编译一次代码需要15分钟。假设问题是某行代码引起的,估计需要一天时间才能找到。如果是多行代码组合影响的问题,时间会更长。而且即使找到了代码,也未必知道原理是什么。所以我选择**方法2**,如果不行,再回到方法1。分析步骤:运行时发现:812先打开代码内存1G以内,编译运行内存2G,关闭Xcode,然后然后打开内存2G816第一次打开代码内存在1G以内,编译运行时内存6G,关闭Xcode后内存6G。关闭Xcode并再次打开它。这个时候Xcode没有运行,所以推测他在做一件事情:读cache缓存文件:大家都知道Xcode编译一个新项目慢,但是编译第二次就快了。那是因为他把编译结果保存在了缓存文件中。第二次编译只读文件,不编译自然会快一些。缓存文件存储在“/Users/你的用户名/Library/Developer/Xcode/DerivedData”目录中。812和816版本的缓存文件对比如下:初步可以看出缓存文件的数量是一样的,只是大小相差比较大。所以接下来就是找错了:谁变大了一番查找,发现每个类都会生成三个文件:.o文件:二进制目标文件,不多说了。dfile:文本文件,记录了该类依赖的所有文件路径。dia文件:未知的二进制文件,但比较大的是一部分dia变大了,另一部分没变。我试着用二进制工具打开看了看,惊喜不已:这不是警告吗?我的抱怨又来了:是谁啊!起来!**写了4Gwarning!**继续分析:那么到底是什么原因造成的至于warning,面对上千个.dia文件,心都碎了。幸运的是,我找到了一个可以交流的朋友。他正好扫了一下警告码,发现某组码中816比812多了107条警告。我们发现了107个警告码,查看了提交记录,就在大家反映卡住了之前。看起来就是这样。我们解决了warning,clean重新编译,问题解决。问题虽然解决了,但是还有2个问题:为什么会提交107警告?只有107个警告。为什么会导致内存飙升?我们还有数百条警告。为什么没事?问题一:只有一行代码触发107个警告苹果对nonnull相关警告的潜规则如下:Xcode6以来提供的新特性,可以声明一个函数的参数是强制的(nonnull)还是可选的(nullable),这将使代码更加严谨。我们推荐使用兼容的老代码:整个头文件没有nonnull/nullable声明,编译不出错对新代码要求高:只要在代码中加入一个nonnull/nullable,其余的代码也必须加上,否则每隔一个界面都会有一个警告。因此,本案涉及的代码是一个老旧的工具类,有107个功能。新的一行代码添加了nonnull。所以有107个警告题2:比如有A、B、C三个类,A.h有警告,.dia文件会包含如下信息:insert'_Nullable'ifthepointermaybenullinsert'_Nonnull'if指针永远不应该为nullA.m文件的绝对路径。A.h文件的绝对路径。A.m文件前几行引用了A.h,在A.h的位置有warning警告。:简而言之,一个警告的信息大约是1k。如果B引用了A,B的.dia文件包含了以上所有信息,还有多个B文件路径,即B的描述信息超过了A。如果C引用了B,B在头文件中引用了A,并且描述信息C的大于B的,所以在工程上,107warning的文件dia有130k左右。所有直接和间接引用的文件数量约为2500个,单个文件超过130k。文件大小约为350M。另外,模拟器有2个cpu架构(i386/x86_64),会生成2个文件,缓存中还有一个聚合的dgph文件。以及文件在内存中结构化后所占用的内存空间。所以最后翻了一倍,达到了4G内存占用,这也无可厚非。结论:警告不要忽略,尤其是头文件中的警告,会被多处引用,导致描述信息过大。尽量不要在头文件中导入头文件,这样会造成引用过多,将问题放大。后续:818版本修复了core中的所有nonnull问题。跟进逐步清除警告为零,修复内存占用如图PS:这是Apple的bug吗?我觉得不如自己挖个坑把自己埋了。【本文为专栏作者《阿里巴巴官方技术》原创稿件,转载请联系原作者】点此查看作者更多好文