|
|
51CTO旗下网站
|
|
移动端

更小的结构

《iOS和macOS性能优化:Cocoa、Cocoa Touch、Objective-C和Swift》第7章内存:陷阱和优化技巧,本章将围绕这个话题来进行讨论。除此之外,我们将展示一些陷阱,尤其是在Objective-C 代码中经常出现的问题。本节为大家介绍更小的结构。

作者:李俊阳 等译来源:电子工业出版社|2018-07-17 16:55

更小的结构

一旦你消除了内存泄漏,避免了Foudation 对象的滥用,并在不使用任何间接指针的情况下紧凑地存储了批量数据,就会发现:数据用更紧凑的内存形式表示将有助于节省内存,并能够使程序运行更加快捷。不仅数据移动的次数变少,同时还能够节省珍贵的高速缓存,从而减少主内存等待的情形,甚至避免更糟的情况——缺页故障进入二级存储器中。考虑到如今机器的实际情况,我们不用再在空间与速度之间做出妥协;不过,结构的尺寸越小,其执行速度自然也会越快。

因此,首先不要随意浪费空间,但可悲的是,浪费空间既容易又极为常见。例如示例7.2 中这个描述日期的示例,它是从一个热门的真实日历应用中截取的。即便对于这些取值范围在0~24、0~31 或者0~60 之间的值而言,使用标准的32 位整数进行存储也已经是极大的浪费了,但是作者似乎不满足于此,不假思索地就用NSUInteger 来替代unsigned int。因为这种做法需要6×8=48 字节的内存,可以想象,在日历应用中将会有海量的日期表示。

示例7.2 在日期表示中,随意用了64 位的数字类型

  1. typedef struct {  
  2. NSUInteger year,month,day;  
  3. NSUInteger hour,minute,second;  
  4. } date_time; 

这段代码可以简单地用示例7.3 中的位域表示方法来替代,这并不会损失所需的精度,只是限制了未来的日期“只能够”到几百万年以后。这种表示方式只占48 位(也就是6 个字节),是之前的12.5%。由于编译器很可能会将这些字符填充到至少8 个字节,所以我们还可以考虑对年份再分配16 位的大小,让年份能表示128 亿年的范围,这足够用到下一次软件更新了。这个简单的修改砍掉了几兆字节的内存占用,如果再算上几百万用户所节省的数量,就会发现节省了惊人的内存:足有几太字节之巨!

示例7.3 更为紧凑的日期表示

  1. typedef struct {  
  2. unsigned long year:21,month:5, day:5, hour:5, minute:6, second:6;  
  3. } date_time; 

要避免的另一个误区就是子类的滥用。还是以日历应用为例,它所使用的主要模型对象是“事件”,但是由于某个不可考的历史缘故,这个模型对象继承了NSView 类。仅仅是将父类替换为NSObject 就能节省几兆字节的空间。

借助64 位转换机制,许多数据类型已经从32 位扩展到了64 位,比如说NSUInteger和NSInteger,此外还有GFloat。对于临时变量和消息参数而言,使用这些类型是没问题的,但是对于实例变量而言,验证其真正需要多大的范围和精度才是有意义的。这里举一个反例,CGColor 的定义中曾经包含了CGFloat 类型的组成域,而现在则是变成了64 位的C 语言double 浮点数类型。考虑到人类的色彩视觉只能够区分出最多约 1000 万(107)种颜色,因此用 24 位数字就可以表示了,而每个颜色的组成域就有64 位的大小(所以对于RGB 而言总共就占了192 位的空间,也就是1038 种组合方式),看起来有点连篇累牍了。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

程序设计实践双语版

程序设计实践并不只是写代码。程序员必须评论各种折衷方案,在许多可能性之中做出选择、排除错误、做测试和改进程序性能,还要维护自己或其...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊