`
hongtoushizi
  • 浏览: 376914 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

Power Profiling: MQTT on Android (1)

    博客分类:
  • mqtt
阅读更多

Power Profiling: MQTT on Android

Introduction

Recently I’ve been doing a lot with MQTT on Android, in particular because it’s such a good fit. Not only can it be used to provide immediate push notification capability, but it also provides low latency, guaranteed messaging over fragile networks and efficient distribution to one or many receivers. Even better, it does all this with small message sizes (minimising the amount of bytes flowing over the wire) and low power usage.

The other great thing about MQTT is that there’s loads of information about it on the web. The specification is fully available, it’s about to be an open standard and it’s also been fairly well adopted by the hobby & hacker crowd, so there’s loads of blogs and tutorials all about it.

One thing I have noticed though, is that, while most people who’ve used MQTT know that it uses extremely low amounts of power on mobile devices, I couldn’t find any definitive power figures. It’s mostly just anecdotal evidence, and so I thought I’d try collecting some. This post details what I did & the results I found.

What was I testing?

Basically it’s a very simple application that calls a custom Android wrapper around a standard Java MQTT client offered by IBM (the one that currently ships with WebSphere MQ Telemetry, for those in the know). All the MQTT work is done in it’s own thread and messages flow in and out between this and the test application through Handlers. It’s not really worthy of a screenshot, but if you’re really keen, you can find one here.

The custom wrapper is one that I’ve created for some things I’ve been doing at work, so unfortunately I’m not able to post the code (right now); but if you imagine a couple of Handlers for getting messages in and out, an Alarm Manager for sending Keep-Alives and some special error handling, you wouldn’t be far wrong.

How did I test it?

I’ve written up a separate post here on the generic approach I used to capture and process the power usage data. In terms of specifics for this testing, I used the Android application described above along with a simple desktop application that was used to send data to / receive data from the Android application. The tests were kicked off manually by myself, either by clicking a button in the Android app or by starting a process in the desktop application, but the timing of events was captured automatically – which allowed me to normalise for any delays from me starting things off.

Caveats / Specifics

  • The power profiling was performed on my HTC Desire, running Android 2.2 – Build 2.33.161.2 CL284385.
  • Throughout this article I refer to the power usage in terms of % Battery / Hour. This refers to the % of the fully charged capacity of my phone’s battery that is used per hour. My phone has a standard Li-Ion battery that is rated at: 1400mAh & 3.7V.
  • The tool I used to capture the power usage data (PowerTutor) uses real data, combined with a power usage model for some aspects. This model has been tailored against the type of device I used for this testing and is reported to be accurate to within 0.8% on average, with a 2.5% margin of error. If you’re interested, you can find out more here.
  • I’ve tried my best to produce correct, consistent and usable results; however I am human and so there’s a chance I have made mistakes somewhere. As such, these figures shouldn’t be treated as Gospel, but I would expect them to be representative of what you could expect to see.

Results

Keep Alive

The first thing I tested was how much power does it take to simply maintain an open MQTT connection, with no messages flowing over the wire. To do this, the MQTT client needs to send a keep-alive message every so often to maintain the connection channel and also to let the server know it’s still connected. I tried a number of different keep-alive intervals and the results are summarised in the table below:

  % Battery / Hour Keep Alive
(Seconds) 3G Wifi
60 0.77641278 0.0119021
120 0.38884457 0.0062861
240 0.15568461 0.00283991
480 0.07792208 0.00134018

 
As you can see, the figures are fantastically low. 3G is probably of the most interest to people, and, even with a relatively short keep-alive interval of 60 seconds, it only costs ~0.8% of the phone’s battery per hour to maintain an open connection; with immediate push notification capability (one of the big selling points of MQTT on Android). And it’s an inverse relationship after that – with a doubling of the keep-alive interval, halving the battery usage.

Personally, I tend to go for a keep-alive interval of 240 seconds; which provides timely detection of the disconnection of the client/server balanced against suitably low power usage (~0.16% per hour on 3G).

As a brief aside: It was suggested to me that some mobile providers will purge a 3G TCP/IP connection if there’s no activity on it for over 10 minutes, however I did try a keep-alive interval of 960 seconds (16 minutes) and everything seemed to behave correctly. Though I guess this could be provider specific (I’m with Vodafone).

Sending

The next thing I looked at was sending messages from the phone. I found it somewhat difficult to get sensible & consistent figures for sending a single message and so I decided to scale up to sending 1024 messages, of 1 byte a piece, as quickly as possible. This also helped to emphasise the difference between the different Qualities of Service (QoS – assured delivery level). The results are shown in the graphs below:

Note: You can click & drag on an area of the graph to zoom to it. Single click anywhere to zoom back out.

3G – Send 1024 x 1 byte messages – Total mW

mW
0
50
100
150
200
250
0
200
400
600
800
1000
1200
 
  QoS 2
  QoS 1
  QoS 0
  1 second period

Wifi – Send 1024 x 1 byte messages – Total mW

mW
0
50
100
150
200
250
0
100
200
300
400
500
 
  QoS 2
  QoS 1
  QoS 0
  1 second period

As you can see, the QoS 0 messages complete the fastest, followed by the QoS 1 and then the QoS 2. This is because the higher the Quality of Service, the more reliable the message delivery, and this has an associated overhead and delay; as it requires additional messages to flow between the client and server to confirm delivery.

Unfortunately this makes it kind of hard to compare the different levels for battery usage, as QoS 0 uses more power per second (most of this is made up of CPU usage), but for a short amount of time, whereas QoS 1 & QoS 2 use much less power per second, but each for much longer. However, if we use a certain amount of poetic licence, we can extrapolate from the data to say how much battery would it cost to send continuously at each level for an hour, how many message would be sent in this time and from that get the comparative battery cost per message*, which I’ve outlined in the tables below:

3G

QoS % Battery / Hour Messages / Hour % Battery / Message *
QoS 0 15.12 614400 0.000025
QoS 1 16.87 23938 0.000705
QoS 2 17.66 15489 0.001140

Wifi

QoS % Battery / Hour Messages / Hour % Battery / Message *
QoS 0 2.02 368640 0.000005
QoS 1 0.93 26144 0.000036
QoS 2 0.89 13704 0.000065

 
* – This is a bit of a silly metric. Firstly, you wouldn’t tend to use MQTT like this, it’s more focused on providing an open channel for push notification and a more sporadic style of message sending & receiving. Secondly, there is a fixed cost in having the Wifi or 3G active and so the actual cost of just sending a single message would be higher. However these figures do serve to indicate the difference between the three qualities of service and hopefully give you an indication of the battery usage involved.

If you’re interested in seeing how the power usage breaks down into the different categories (CPU & 3G/Wifi) you can click here for some more pretty graphs.

Receiving

After sending, the next thing I looked at was receiving messages on the phone. To be consistent with the sending results, I sent 1024 messages, of 1 byte a piece, to the phone, as quickly as possible. The results are shown in the graphs below:

3G – Receive 1024 x 1 byte messages – Total mW

mW
0
50
100
150
200
250
300
350
0
200
400
600
800
1000
 
  QoS 2
  QoS 1
  QoS 0
  1 second period

Wifi – Receive 1024 x 1 byte messages – Total mW

mW
0
50
100
150
200
250
300
350
0
100
200
300
400
500
 
  QoS 2
  QoS 1
  QoS 0
  1 second period

Again we can see that the QoS 0 messages complete the fastest, followed by the QoS 1 and then QoS 2 (for the same reasons mentioned above). It takes slightly longer for all the messages to be received and so the power per second for each QoS is much more comparable, as the CPU load is spread out. However, to be consistent, I have extrapolated the data as before into the tables below.

A couple of other things of notice are the two erroneous patterns in the QoS 2 flows. For 3G we see the message receiving stop for about 20 seconds before continuing, and for Wifi we briefly see a large spike in power usage about half way through. Unfortunately I don’t have anything to explain this, the connection doesn’t drop and there’s nothing immediately obvious. I’m going to repeat these tests when I get time and I expect this will turn out to be a one off anomaly, but for the moment I thought you might appreciate the experimental authenticity :)

3G

QoS % Battery / Hour Messages / Hour % Battery / Message *
QoS 0 16.03 35446 0.000452
QoS 1 17.48 27510 0.000635
QoS 2 15.80 13552 0.001166

Wifi

QoS % Battery / Hour Messages / Hour % Battery / Message *
QoS 0 0.59 64673 0.000009
QoS 1 0.70 32914 0.000021
QoS 2 0.86 17226 0.000050

Again, if you’re interested in seeing how the power usage breaks down into the different categories (CPU & 3G/Wifi) you can find them by clicking here.

Connect & Wait

Finally, I thought I’d just briefly include a couple of graphs showing the general shape of creating a connection and leaving it running in the background (i.e. the initial connect and subsequent keep-alives, with a 60 seconds keep-alive interval):

Note: These are stacked graphs. CPU on top of 3G / Wifi.

3G – Connect & Wait

mW
0
20
40
60
80
100
120
140
0
200
400
600
800
1000
 
  3G
  CPU
  1 second period

Wifi – Connect & Wait

mW
0
20
40
60
80
100
120
140
0
25
50
75
100
125
 
  Wifi
  CPU
  1 second period

What next?

This has been a relatively shallow foray into power profiling MQTT on Android and now I’ve done it I can think of a whole host of other things that I’m interested in doing. Things such as:

  • Testing the effect of message size on sending & receiving.
  • Testing power usage when running on fragile networks that keep dropping & being re-established.
  • Testing more realistic usage scenarios – e.g. messages flowing much more sparsely and/or at less predictable intervals.
  • Comparing MQTT with it’s possible alternatives, e.g. HTTP, C2DM, etc. Although it may be difficult to create a scenario where they all do the same thing so that they can be measured equally.
  • Open sourcing the code I’ve created – this is something I need to figure out with work, but, if possible, I’d love to get the code I used out there. Not only because I think people would find it really useful to have an Android MQTT component they could just drop into their projects, but also so that people could repeat the tests I’ve done here and try out new scenarios they’ve thought up themselves.

Just need to find the time :)

So, hopefully you found that interesting and maybe useful. If you have any comments, questions or suggestions, I’d be happy to hear them – but please do keep in mind the things I mentioned in the Caveats section above :)

 

 

转载自: http://stephendnicholas.com/archives/219

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics