Socket connections and Polling. Which is a better solution in terms of battery life?
Asked Answered
J

3

43

So... I'm making an application for Android. The application needs to send and receive realtime chat data (needs to be a socket) but it also needs to send commands (which don't as the client knows when it is sending something).

I need to know what is a better solution in terms of saving the user's battery.

a) Opening and Closing the connection every time a command is sent, if the chat tab is opened then keep the connection constant.

b) Keep the connection constant all the time.

I've taken a look around the internet but have gotten mixed answers, some say keeping a persistent connection is bad for battery life and others say that it isn't (Example: "Are you asking if holding a TCP connection open will drain battery-life? Maybe I am WAY off here but, holding a connection open shouldn't waste battery life... If you think it will I would love to know where you got that information. It sounds SO strange to me.")

Or if there is another solution that would be better. I don't think that Google's C2DM would be very useful at all in this situation either.

Basically, what drains the battery more: having a persistent connection, or opening and closing the connection unless the chat tab is open?

Thanks!

Jegar answered 3/8, 2012 at 4:44 Comment(1)
It seems very reasonable to assume that polling would consume more power, since you're opening and closing a connection each time you poll (in addition to sending the data back and forth). I'd be surprised if anyone has actually done any benchmarking on this already, so maybe you'll have to be the first in order to get a concrete answer. :)Theroid
M
68

Keeping an idle TCP socket connection open (with no data being sent or received) will not (or at least, should not) consume any more battery than having it closed. That is because an idle TCP connection uses no bandwidth or CPU cycles(*).

That said, keeping a TCP connection open for extended periods may not be a good option for a mobile device, because TCP connections don't interact well with computers that go to sleep. The problem scenario would be this: your Android user puts his Android device to sleep while your app is running, and then the remote user's program (or whatever is at the other end of the TCP connection) sends some data over the TCP stream. The remote user's program never gets any ACKs back from the Android device, because of course the Android device is asleep, so the remote device's TCP stack assumes that the TCP packets it sent must have been lost, and it responds by increasing its timeout period, decreasing its TCP window size (aka number-of-TCP-packets-allowed-in-flight-at-once), and resending the TCP packets. But the Android device is still asleep, and thus the same thing happens again. The upshot is that a few minutes later, the remote end of the TCP connection has slowed down to the point where even if the Android device was to wake up, the TCP connection will likely be too slow to be usable -- at which point your program will need to close the bogged-down TCP connection and start up a fresh one anyway, so why bother trying to keep it open?

So my recommendation would be to go with option (a), with the stipulation that you close the TCP connection as part of your device-is-going-to-sleep-now routine.

One possible caveat would be if Android has a feature where keeping a TCP connection open causes the WiFi or cell-network hardware to remain powered up in a situation where it could otherwise be put to sleep -- if that is the case, then the Android device would pay a battery cost for powering the antenna, which it wouldn't otherwise have had to pay. I'm not aware of any Android logic like that, but I've only used Android a little so that might just be ignorance on my part. It might be worth testing for, at least.

(*) Well, technically TCP does send a "keepalive" packet every so often while a TCP connection is open, and that does use some CPU cycles and antenna power... but the default interval for sending keepalive packets on Android is two hours, so I doubt the power used for that would be noticeable.

Manhour answered 3/8, 2012 at 5:32 Comment(9)
Thanks heaps for your amazing answer! You explained that really well. With the caveat you suggested, I think it is safe for my application to close the connection whenever the device goes to sleep - as it really only needs to be working when the user doing things on the phone. So even if it does do what you said it might, always disconnecting should fix that. When it reconnects I can probably send any data that the phone missed out on while it was disconnected. Thanks again for your answer!!Jegar
TCP Does not send a keepalive packet by default. TCP will send a keep alive only if that option is enabled on the socket. You must enable it. I suggest leaving it disabled and doing your own heartbeat. In my experience managing your own heartbeats is better as it lets you know whether the connected client has malfuctioned, while the automatic TCP keepalive may not let you know this.Aerometeorograph
@WilliamMorrison "Managing your own heartbeat!!" what does it imply here.?Gummosis
It means sending your own heartbeat packet. Heartbeats occur periodically. This is necessary as if you have 2 connected TCP sockets, and neither are sending data, they may or may not be connected. You need to attempt to transfer data to confirm the sockets are still connected.Aerometeorograph
Thanks for the insightful answer. Could you please cite any reference for the same : an idle TCP socket connection open does not consume any CPU cycles (for less than 2 hours) ?Rhett
Just make your app stay awake in sleep mode.Samford
If your app is running, then the CPU isn't asleep. It's possible to force the the CPU to wake up periodically, of course, but doing so drains the battery.Manhour
Uhm.. is this the same case for an UDP socket?Exon
@Exon there's no such thing as a UDP connection, so it's not clear that the question applies to UDP. If you're asking about whether simply keeping a UDP socket open would require more CPU cycles than closing, then the answer is that it would not.Manhour
R
1

In order to actually keep a connection open, you'd likely have to send heartbeat signals back and forth, as any stateful routers between the android device and your servers would forget about the connection after a relatively short time out.

Which is better all depends on how long you think you'll go without needing to connect to the server. If you're connecting about once every 30 seconds or so most of the time anyways, definitely keep the connection open, but if not, you might be better off closing it.

Ronna answered 3/8, 2012 at 5:49 Comment(0)
A
1

The battery is very much related to radio state transitions on 3G from DCH/FACH/IDLE. If you want to have an app which is energy efficient you should send as much of data as possible on limited time interval irrelevant of a persistent connection or not...

Abeokuta answered 14/6, 2013 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.