为了提高应用程序的性能和电池寿命而优化I/O

本文翻译自苹果WWDC的文章 Optimizing IO for Performance and Battery Life

系统资源包括以下方面:

其中IO:

对于用户的影响包括以下方面:

苹果的I/O使用的理念:

1. 在app中减少I/O的使用。
2. 使用正确的线程去处理I/O操作。
3. 采用适当的api去处理I/O。
4. 测试和估量app的I/O性能。

一、在app中减少I/O的使用

最好的提高应用程序的I/O效率的方法就是减少I/O的使用。

下面是一个简单的框图,代表一个现在使用设备的组成以及它们对电池寿命的影响:

当你的应用使用IO的时候会在CPU上运行代码,使用内存,从磁盘读取数据,网络激活的话还会使用网络,所有这些操作的能量都来源于电池的提供。

下面看两个用于减少I/O使用的最佳实践

1.Caching

这里主要的思想就是在内存中创建一个拷贝你的磁盘的数据而不是每一个操作都去硬盘中读取数据

你应该由你的数据的访问模式来决定是否你app中的数据需要被缓存到内存中。对于经常写的或更新的数据,将其缓存在内存中可能是一个不错的选择。

此外,数据从磁盘读取是一个较重负荷的处理步骤,例如,解压一个图像文件的数据可能是一个很好的应该使用缓存的例子。

和I/O一样,内存也是系统中共享和有限制的资源,因此,你也应当小心的使用。

如果你决定为你的应用创建缓存,我们建议您使用NSCache的相关Api,因为系统已经你妥善处理了一些内存方面的压力。

2.Coalescing I/O(调度I/O)

这里的主要思想就是将你的I/O操作推迟到合适的时间去执行

主要有几个方面:

  1. 推迟I/O的操作。将I/O的操作放到系统中更合适的时间去操作。
  2. 由于I/O技术的工作方式,更大,更少的I/O操作对你的系统来说是高效的。
  3. 使用app状态改变的通知。例如,应用程序在后台时调度I/O。
  4. 使用集中式任务调度(MACOS)。

下面介绍一个调试I/O性能的工具:

这显示你app中所有系统资源中正在使用的所有实时数据。有CPU、内存、能源、网络和磁盘。

二、Use the Right Thread

程序运行规则:

主线程是特殊的,它的使用主要有两个目的,

  1. 第一个主要的目的是处理输入。例如当我点击一个button的时候,主线程能够接受这个响应并且处理响应。
  2. 另外,主线程用于更新UI。 例如画图,动画等。

当你的主线程闲置的时候,它已经准备好接受可用响应输入或更新你的用户界面。但是如果你在主线程上做一些其他的操作,例如执行耗时较长的任务,这和较重的图像处理一样,这种操作会使主线程变得很忙碌,意思就是主线程不是空闲的,这时候你无法响应输入或者更新UI。另外,我们现在关注的是,你不应该在主线程上做I/O操作。正如我们看到的,I/O是很昂贵的系统资源,需要我们妥善管理

举个例子:

最后还有一个服务质量(SOQ):

一旦我们选择了一个服务质量类, 有两种主要方法,您可以在您的应用程序指定的服务质量。

  1. 提供异步运行的代码块时,它将使用后台的服务质量。    
  2. 此外,如果你使用操作队列或操作的API,这两个有一个的服务质量属性,您可以设置,如utility。

补充:
新的qualityOfService(IOS 8)属性替换了ThreadPriority。这些新的语义允许应用程序推迟非关键工作,以确保始终如一的用户体验。
NSQualityOfService枚举定义了以下值:

  • UserInteractive:在实现图形密集型相关工作时使用UserInteractive QoS,比如滚动或动画。
  • UserInitiated:在实现用户精确请求请求相关工作时使用UserInitiated QoS,但不要求精确到毫秒,比如动画。例如,如果用户打开email app马上查看邮件。
  • Utility:Utility QoS用于执行已经由用户请求自动发生的任务。例如,电子邮件应用程序可以被配置为每隔5分钟自动检查邮件。如果系统是非常有限的资源,而电子邮件检查被推迟几分钟这也是被允许的。
  • Background:Background QoS用于执行用户可能甚至都没有意识到正在发生的工作,比如email app可能使用它来执行索引搜索。

三、Adopt Appropriate APIs(使用合适的api)

1.Asset Catalogs

概述:

  1. app图标和启动图。
  2. 不同的设备和不同的尺寸。
  3. 采用SpriteKit构建游戏时,也可以使用Asset Catalogs来管理游戏相关资源。
  4. 管理随需而变的资源。
  5. 并行开发的watch资源??

对I/O方面的好处
储存影响:

  1. 较低的磁盘占用率。
  2. app切片。

性能:

  1. 图片加载。
  2. 改善游戏的纹理渲染时间。
  3. app启动时间。

为什么说资源管理目录对I/O来说是高效的?
资产目录有一些很棒的存储效率特性。

  1. 首先,因为资产目录是以一个优化的格式存储所有的图像而不是说以一个个单独的文件,你可以获得一个较低的磁盘占用率通过使用Asset Catalogs。
  2. 此外,像iOS应用程序切片的特点,当你从app Store下载一个应用程序,它使用资产目录中的元数据来确定哪些资源应该下载到你的设备。例如,我下载了一个应用程序到我的iphone,App Store知道它不需要下载任何资源为iPad或不同的屏幕分辨率的iphone,这样可以节省大量的设备储存空间。
  3. 此外,使用Asset Catalogs对性能来说是最好的。因为这种优化的格式,它们存储的图像在加载时可以更快。

事实上,我们已经看到应用程序启动时间有百分之十的改善在切换到资产目录的设备上。

你可能也想得到一个性能上的提升,觉得这一定是很困难的或则耗时的切换为Asset Catalogs,但是实际上,如果你已经使用标准的NSImageUIImage等基本的API的,切换到资产目录是容易的。

资产目录是一种简单高效的方式来管理你的应用程序的资源。

2.Storing Your Data

序列化的数据格式有以上的特性,但是最大的问题是它们不是一个数据库,也正式因为和这个原因,每一次小的更新都需要数据文件的重新写入磁盘,这对I/O来说是比较坏的影响。

你所有的数据存储需求,建议使用苹果SQLite数据库框架core data。core data,是一个Cocoa应用程序开发框架来管理你的应用程序数据。它处理数据持久性使用SQLite作为后台存储。

它会自动管理对象,对象图表,和这些对象之间的关系, 能让你轻松高效地管理你的数据。具有特点:

  1. 数据持久化。
  2. 管理对象以及对象图表。
  3. 能进行改变跟踪,会让你更改,撤消和重置等操作数据模型。
  4. Core Data是完全集成在Xcode工具链中,这样您就可以直接在Xcode UI上构建可视化数据模型。

四、Test and Measure

让我们来看看怎么测试你的应用程序的I/O性能。

首先推荐的是在不同的设备上测试你的应用程序

改变网络环境,可以测试在正常网络环境以及最差网络环境下使用你的app

环境变化:

  1. 多任务情况在你的app的I/O性能的影响
  2. 系统会尝试在内存和I/O使用情况下保持一个平衡,测试在内存压力条件下,对你的app的I/O的影响。
  3. 建议重启,重置缓存(系统维护一系列默认缓存来帮助你更好的访问和存储你的数据,这些缓存的状态可能会影响你的app。)

五、总结

1. 我们需要在应用程序中减少I/O的使用,因为这明显影响电池寿命。
2. 将I/O重工作负载从主线程移出, 为UI和动画保持主线程的空闲。
3. 为你执行的工作的意图指定适当的服务质量。
4. 使用Asset Catalog管理资源。
5. 使用Core Data。
6. 测试估量。