Every time your app performs I/O-related tasks, such as writing to disk, it brings the system out of an idle state. Writing to flash memory is especially energy-draining. By writing data less, aggregating writes together, using caching wisely, scheduling network transactions, and minimizing overall I/O, you can boost the energy efficiency and performance of your app.
Optimize File Access
Here are some guidelines for optimizing file access in your app:
Minimize the data you write to the disk. Write files only when their content has changed, and aggregate changes into a single write whenever possible. Avoid writing out an entire file if only a few bytes have changed. If you frequently change small portions of large files, consider using a database to store the data instead.
Avoid accessing the disk too frequently. If your app saves state information to the disk, make it do so only when that state information changes. Batch changes whenever possible to avoid writing small changes at frequent intervals.
Read and write data sequentially whenever possible. Jumping around within a file takes extra time to seek to the new location.
Read and write larger blocks of data from files whenever possible, keeping in mind that reading too much data at once might cause other problems. For example, reading the entire contents of a 32 MB file might trigger paging of those contents before the operation is complete.
For reading or writing significant amounts of data, consider using
dispatch_io, which provides a GCD-based asynchronous API for doing file I/O. Using
dispatch_iolets you specify your data needs at a high level, so the system can optimize your disk access.
If your data consists of structured content that is randomly accessed, store it in a database and access it using, for example, SQLite or Core Data. Using a database is especially important if the amount of data you are manipulating could grow to more than a few megabytes.
Understand how the system caches file data and know how to optimize the use of those caches. Avoid caching data yourself unless you plan to refer to it more than once. See The System Has Its Own File Caching Mechanism in File System Programming Guide.
Several tools can help you monitor the I/O activity your app produces.
fs_usage command-line tool provides a running list of system calls related to activity in the file system. It has options that allow you to specify a timeout, filtering, and more.
fs_usage command provides global file system activity across all running processes, as shown in .
$ sudo fs_usage
To monitor activity for a specific app, you can target it by its process name or ID, as shown inand .
$ sudo fs_usage Mail
16:20:51.693058 open F=30 (_WCA__) ple.mail/Data/Library/Logs/Mail/2015-02-10_AccountManager.log 0.000135 Mail.2315137
16:20:51.693917 write F=30 B=0x64 0.000801 W Mail.2315137
16:20:51.708853 open F=35 (_WCA__) apple.mail/Data/Library/Logs/Mail/2015-02-10_AccountFetch.log 0.000086 Mail.2315137
16:20:51.709179 write F=35 B=0x88 0.000288 W Mail.2315137
16:20:51.709332 write F=35 B=0x7f 0.000007 Mail.2315137
16:20:51.709750 read F=87 [ 35] 0.000005 Mail.2315136
16:20:51.709774 read F=87 [ 35] 0.000001 Mail.2315136
$ sudo fs_usage <pid>
uses options to monitor Mail for filesystem-related I/O activity only, and specifies a timeout of 10 seconds.
$ sudo fs_usage -w -f filesys -t 10 Mail
07:57:32.574069 open F=30 (_WCA__) /Users/yourUserName/Library/Containers/com.apple.mail/Data/Library/Logs/Mail/2015-02-11_AccountManager.log 0.000120 Mail.2705843
07:57:32.574128 write F=30 B=0x64 0.000012 Mail.2705843
07:57:32.587519 write F=95 B=0x88 0.000011 Mail.2705843
07:57:32.587639 write F=95 B=0x7f 0.000004 Mail.2705843
07:57:32.588018 read F=65 [ 35] 0.000004 Mail.2706962
07:57:32.588038 read F=65 [ 35]
See fs_usage(1) Mac OS X Manual Page for complete documentation on this command.
Xcode Debug Navigator
While testing your app in Xcode, choose View > Navigators > Show Debug Navigator to display the debug navigator pane. This pane provides useful information about the state and behavior of your app through a series of gauges. As you test your app, monitor its activity here carefully and look for areas where you may be able to reduce I/O activity. For more detailed I/O analysis, consider profiling your app more extensively with Instruments.
The Disk (see) and Network gauges show the I/O behavior of your app, including:
Amount of data read from and written to disk
Rates of reads from and writes to disk
Network data received and sent
Network data receiving and sending rates
Active network connections
The File Activity profiling template in Instruments (see) can help diagnose the file activity of your app.
This template includes the following instruments:
File Activity—Records file opens, closes, and stat operations.
Reads/Writes—Records reads and writes of bytes to files.
File Attributes—Observes changes to file attributes, such as owner, group, and mode.
Directory I/O—Monitors directory activity, such as links, directory creation, and moves.
As shown in, the instruments in this profiling template present a very detailed representation of how your app is interacting with the file system. Use this information to determine whether your app can be refactored in order to batch activity or otherwise do I/O more effectively and efficiently.
For information about using Instruments to analyze the behavior of your app and diagnose problems, see Instruments User Guide.