Mallow's Blog

A Guide for making Energy Efficient Apps – I

The screenshot below is something much more familiar to any iPhone user. The screen shows the battery consumption by the applications running on the phone. Any developer’s dream is to top the list of Trending Apps, top list apps but definitely not this. As a user, it is obvious that you would delete the application which consumes a huge portion of the charge. High energy consumption by any application discourages the user from using that app anymore. This leads to a reduction in the userbase and ultimately results in the failure of the application. In order to avoid this, we need to make the application energy efficient.

Battery consumption screenshot

Let us see the ways to make an application more efficient in this blog. We will see this under 4 subtopics,

1.Energy basics
2.Possible energy efficient hacks
3.Energy debugging tools
4.Summary

1.Energy Basics:

Before getting into the ways of saving energy it is essential for us to know what is meant by energy in this context. Having a basic understanding of energy will let us work efficiently. Energy equals power times time, i.e. E=P*t. So the longer the time the app consumes power the quicker the battery gets drained. Let’s see how energy is handled in iOS devices. You can see the following image, which represents a typical energy usage chart of an app of an iOS device.

Energy classification

The chart drawn in the graph represents the energy usage of an app and some terms had been added which are,

Idle: The state when the device is idle.
Active: The state when the user is actually using the app.
Overhead: The amount of power that’s needed to bring the device hardware up to be able to do the app’s work and also to put it back to sleep.

To continue further on this topic it would be better to split the energy usage into two as represented in the image above,

1.Dynamic cost
2.Fixed cost

Dynamic cost: Represents the energy usage that the app’s activity is going to consume.

Fixed cost: Its the overhead cost which is must/required to make the app’s activity to happen.

This very blog is going to revolve around there above two main things and let us see how to we can efficiently handle these two to make the energy consumption of the app as efficient as possible.

2.Possible energy efficient hacks:

Everything you do in the device will consume some energy for it to happen. And the following four things plays the major role in it, they are,

Processing screenshot

1.Processing:

Some best practices we can make use to reduce the impact of CPU processing utilization are as follows,

a.Background processing:

Avoid unwanted background actions, i.e., If in case you are performing a background action, for example, fetching new detail in the background, and at the same time the user closes/goes to the home screen or to another app, that particular data is useless and the unwanted background process is happening.

For similar cases, we can cancel the request whenever the user is not actively using the app in scenarios like app goes background. By doing this you can avoid usage of unwanted background processing.

b.Call completion handler:

If your method or any delegate methods has a completion handler make sure you call that completion handler as soon as your work gets done because until you call the completion handler there would be some precious CPU utilization is being consumed. And by calling the completion handlers you are allowing your device to let sleep, else until the completion handler gets called the device is not permitted to get to a sleep state.

The following picture can represent the difference with and without calling the completion handler.

Energy consumption graph

Without calling completion handler

without completion handler energy consumption

2.Networking:

a. Avoid timers as much as possible, Instead, you can make use of

i. Notifications:

Perform certain actions when you receive notification. You can make us of notification like in case your app is a news app and you want the news feed to refresh automatically when some urgent news content is published, in such situation you can post a notification and on receiving that notification you can make use of it making the refresh news feed call which you want.

ii. User interaction:

Here, it’s not always there will be a need for timer based update/action. In most of the case we might not have needed it, and in such cases, you can perform the action only when the user think they need it. Like in the above example if the user wants to see whether any updated news is available you can make use of a pull to refresh action or a refresh button to make the refresh call.

So by making this small tweaks, you can avoid unwanted usage of energy by eliminating timer usage.

b.NSURLSession default session

There are several properties available in NSURLSession which you can make use of to accomplish energy efficiency,

i.WaitsForConnectivity:
A Boolean value that indicates whether the session should wait for connectivity to become available, or fail immediately.

By making use of this property you can avoid unwanted network calls till the network connection is active for making network calls.

ii.Cache:

You can enable and configure cache for NSURLSession which could be used for avoiding re-download of contents which is already downloaded.

You can perform the above operations as follows,

</span>

<span style="font-weight: 400;">// Setup NSURLSession default session</span>

<span style="font-weight: 400;">let config = URLSessionConfiguration.default      </span>

<span style="font-weight: 400;">// Making use of waitsForConnectivity property</span>

<span style="font-weight: 400;">        config.waitsForConnectivity = true</span>

<span style="font-weight: 400;">      </span><span style="font-weight: 400;">// Making use of Cache</span>

<span style="font-weight: 400;">        let cacheDirectoryURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first</span>

<span style="font-weight: 400;">       </span><span style="font-weight: 400;">let cacheURL = try cacheDirectoryURL?.appendingPathComponent("MyCache")</span>

<span style="font-weight: 400;">        </span><span style="font-weight: 400;">var diskPath = cacheURL?.path</span>

<span style="font-weight: 400;">        </span><span style="font-weight: 400;">let cache = URLCache.init(memoryCapacity: 12345, diskCapacity: 123456789, diskPath: diskPath)</span>

<span style="font-weight: 400;">        </span><span style="font-weight: 400;">config.urlCache = cache</span>

<span style="font-weight: 400;">        config.requestCachePolicy = .useProtocolCachePolicy</span>

Minimize retries:

You can reduce the number of retry attempts you are making for making a network call in case of failure.

Set timeouts :

You can explicitly specify timeout for the network calls, by default the system would perform retry

Batch network calls :

If you think a network call is not necessarily to be called then and there, you can combine that network call when performing other network calls.

Background session :

As stated in the batch network calls when you think some network calls are not needed to be done as soon as you perform it, you can hand it over to the System. Yes, you heard it right, iOS provides you with such an opportunity where you can handle your task to the system using NSURLSession background session.

Thus we have seen the first two points. In the next post, we will see in detail about the energy debugging tools and summary of how to go about it.


Bharath R,
iOS Team,
Mallow Technologies.

 

Leave a Comment

Your email address will not be published. Required fields are marked *