ARTS 第七周
Algorithm
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
思路
采用反转一半数字的思路,需要注意的是何时可以判断我们已经反转了一半数字:若为回文数,则反转数不断增加,原数不断减少,当两者相等(偶数)或反转数大于原数时(奇数),即为一半。
解答
1 | class Solution { |
Review
Advancements in the Objective-C runtime
这个 session 来自 WWDC2020 ,介绍了苹果对 OC Runtime 的一些优化。
调整类的结构
以往的类结构中,将只读的类信息结构体(编译器创建)存入 clean memory,以节约内存,而可读写的类信息结构体(运行时创建)存入 dirty memory ,由于不能 page out 而更为昂贵。本次的优化思路是将原来的可读写类信息结构体class_rw_t
拆分为class_rw_t
+class_rw_ext_t
,后者即为该结构体中的动态部分,必须存入 dirty memory ,而剩下的class_rw_t
则可以放入 clean memory。
经过优化后的类可达到 90% 的 clean memory ,系统层面节约 14 MB 内存。
head xxxxx | egrep ‘class_rw|COUNT’
可查看应用class_rw_t
消耗的内存,xxxx 为应用名。
相对方法地址
在类的结构体中包含一个方法列表,每个方法包含三个部分:selector/方法类型编码/IMP 指针,在 64 位的系统中,每个部分占用 8 个字节。
在 APP 的进程内存空间中,包括了各种链接库,这些库在链接过程中会将地址偏移以确定最终的地址,但由于方法实现地址不会脱离当前库的地址范围,方法列表并不需要 64 位的寻址空间,只需要在自己的库地址中查找引用函数地址,因此可以使用 32 位相对偏移来代替绝对 64 位地址。
这样做的优点有:
- 库被加载后不需要修正指针地址,因为偏移量是相同的
- 方法可被保存到只读存储器中,这会更加安全
- 使用 32 位+偏移量在 64 位平台上节约了一半内存
而针对 Method Swizzling 的情况,需要额外维护一个映射表以保存方法实现的地址。因此相较于优化前,Method Swizzling 的代价变大了。
Tagged Pointer 格式变化
优化前的 Tagged Pointer 会将标识位(是否为 Tagged Pointer)存在指针地址的最低位,之后的三位用来标识数据类型,包含 7 种情况。其中的OBJC_TAG_7
类型还会将接下来的后 8 位用于记录拓展类型,以支持如UIColor
之类的对象。
本次优化在 ARM 中将上述标识位的位置做了调整,将最高位作为 Tagged Pointer 的标识位,拓展类型位于之后的 8 位,而数据类型标识放在最低三位。
这样的调整会对objc_msgSend
有一定优化,因为 msgSend 的会判断指针类型,包括普通指针、 Tagged Pointer 或 nil 。将标识位放在最高位可以一次判断出是否为后两者,而不用分别检查,节省了条件分支。
Tip
记录一下 Rx 中的一个常用操作符flatMap
。
该操作符的意思是将源Observable
的元素应用一个转换方法,将其转换为Observables
,然后将这些Observables
的元素合并(flat)之后发送出来。
Share
本篇文章比较全面的介绍了 iOS 端重要的几个性能监控的指标及其原理和方案,是一篇不错的总结。