0

I'm currently working on an Android application that broadcasts the location of the device every 5 seconds.

Pseudo showing current app process:

deviceLocation = getLocation()

if (hasChanged(deviceLocation)) {
    putRequestWithLocation();
} else {
    // Send heartbeat so we at least know device is still connected
    putRequestEmpty();
}

This is the actual Java code used to send the put request:

// The data variable is a comma separated string, e.g:
// 50.343423,-1.349545,1 (lat, lon, vehicleid)

try {
    URL url = new URL(apiEndpoint);
    HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setRequestMethod("PUT");
    OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());
    out.write(data);
    out.close();
    httpCon.getInputStream();
} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

My question is twofold:

1) Can any optimisations be made to the HTTP PUT request written above to reduce packet size and therefore optimise network usage?

2) Would a socket connection be a better idea based on how frequently we're sending vehicle data?

Thanks in advance!

  • Are you actually running into an issue or just trying to optimize the request? What stands out to me is not the request code but the high frequency of calls. – Dan Wilson Oct 23 '18 at 18:37
  • You might want to consider how accurate your location data is and how far your device can possibly move between updates. – Dan Pichelman Oct 23 '18 at 19:11
2

Perspective

Some back of the envelope calculations to put things into perspective:

Let's assume that handling a single such request consumes 2 kB of data. That's 24 kB of data per minute, 1.44 MB per hour. 34.56 MB per day, 1.04 GB monthly. That's neither a big nor a small number (at least for a typical consumer/business plan over here in eastern Europe). You might consider just warning the user.

Inefficiencies and their removal

There are three sources of overhead for you:

  • TLS handshaking (you do use TLS, yes?)
  • HTTP headers
  • Inefficient data encoding

going over them:

TLS handshaking

Here you want to keep your connections alive - so those 5s heartbeets are not a bad idea actually (since the keepalives would be sent anyway).

HTTP headers

Here the idea of sending raw data instead of HTTP request is quite good - it saves you a good few hundred bytes on every request but you need your own framing (usually just data length preceding the actual data, say two bytes).

Data encoding

Whatever you do - good binary encoding will always be tighter then a human-readable, textual representation. You can represent longitude and latitude as 32-bit unsigned integers - looking at your examples 9 decimal digits with fixed precision are enough. Knowing your chosen encoding also helps - I'll show that later. Personally I recommend Google's Protocol Buffers for this.

After

Optimized back-of-the-envelope. Let's assume we have the following Protocol Buffer message:

message Status {
  fixed32 session_id = 1;
  fixed32 lat = 2;
  fixed32 lon = 3;
  bool vechicled = 4;
}

How big is this message? I won't go into the details but depending on the state of vechicled it should be either 15 or 17 bytess - default values such as false for bool are not even encoded. Add in message length and we get 19 bytes of data. Sending the same stuff over HTTP would make just the requests roughly 200 bytes or so with all the required headers. Throw in reopening the connections, TLS handshakes and well... The user might be thankful.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.