Batching calls to Google APIs (Javascript)

One of the benefits of having a standardised API layer across all the (recent) Google APIs is that a bunch of features come for free. One of these handy items is batching, which is generally pretty easy to do.

For example, an awful lot of Google+ Sign-In implementations retrieve both the signed-in user's profile information and the collection of friends the user shared with the app when the user connects. This generally necessitates two calls, two connections, and two lots of overhead, but can be easily combined into a single request.

If you take a look at the Google+ Javascript QuickStart you'll see there is a profile function and a people function, each making a call to gapi.client.plus.people.something, and then request.execute. We can replace that with a single function that combines both, and looks a little like this:

All we've done here is created each request, and a new RPC batch with gapi.client.newRpcBatch(). It's called RPC batch as we're actually using the JSON RPC endpoint here - every API exposes both RPC and REST-style URL structured endpoints automatically, but the RPC one is a little easier to work with for batching.

We then add each of our requests (even though they're to different parts of the API) to the RPCBatch, and associate the callback with them. The other parameter we could pass in there is 'id', which would allow us to write a single callback function and pull out the requests we wanted if that was easier. One thing worth noting is that the callbacks are slightly different - in the batch version, the response we receive is a object containing the request ID and a 'result' object, which is equivalent to what we would have received when calling directly. This means there's an extra line of code to unwrap that, but otherwise the functions are the same as in the quickstart.

Finally, we just call rpcBatch.execute() and our callbacks are fired. For an idea of the savings, in a completely unscientific test I tried the standard quickstart and found the average time to fetch profile was around 180ms, and friends 500ms. With the batching operation, I found that the total was around 500ms - the friends was completely covering the time of the profile retrieval.

Where this type of thing really helps is in situations like on mobile, where establishing a TCP connection can really be painful. You can read more about the RPCBatch options in the Google APIs Javascript Client Library documentation.

Comments

  1. Is the batching faster because you don't have to establish the connection twice, or because it allows the server to process the requests in parallel?

    I would've thought keep-alive would eliminate the connection overhead of the second request, though it doesn't allow your requests to be processed in parallel, since the server doesn't see the second request until it's sent the response to the first.

    I guess mobile browsers might also be unnecessarily opening up multiple connections, when it would be faster to wait for the request on the first connection to complete. But hopefully they only open connections speculatively, and only use the second connection if it becomes available before the first is.

    ReplyDelete
  2. It's sort of better for both reasons, in different situations. It all depends on the browser (limits of connections to a given host vary) and the other requests made on the page. Browsers do an awful lot of clever stuff (e.g. chrome will create backup TCP connections if the first one isn't handshaked in a certain time in case the syn/synacks were lost, it will also do some TCP pre-connect if it thinks the connection is likely and so on), which should help the situation, but in general reducing the number of requests has a good chance to work out well. YMMV with the overall gain, but I'm generally of the opinion the batching is always at least worth trying.

    ReplyDelete

Post a Comment

Popular posts from this blog

Client-Server Authentication with ID tokens

Common problems with Google+ Sign-In on Android

TLS and ZeroMQ