Using gzip compression when making HTTP requests in Windows Phone apps

Bandwidth and data consumption on mobile devices remain one of the most critical resources an app consumes on any platform. A majority of users have limited data plans and actually pay more if they use more data on their mobile devices. This makes it critical for us, as app developers, to ensure our apps consume as less data as possible. And when apps download less data, they perform better and become more responsive too.

I overlooked this myself earlier but fixed it as soon as I noticed. In fact, a lot of apps is store are not using compression including some heavily used apps like famous YouTube clients. The response size for 10 entries in most popular list from YouTube is ~50KB by default and ~7.4KB when compression is used, that’s 85% less data downlaoded. It varies for each request but the savings are somewhere from 30% to 85%.

Overview

We all use compressed archives on PCs in one format or the other like zip, rar, 7z and others. For the web, what it really means is that the data being transferred over the network is compressed and hence uses less bandwidth. This is defined in http spec as a standard. When a client, like your app, sends a request, it can tell the server that it’s capable of handling compressed response in Accept-Encoding request header. The server then sends the response in compressed format (if it’s capable of doing so) and tells the client using Content-Encoding response header. Obviously, the server and client both not only need to support this but also send consent that this capability is used. This is how http works for everything so no surprises there.

Good news is that you don’t have to implement compression to take advantage of this as the HttpClient library you should be using added supports for this over a year ago. Unfortunately, this wasn’t the case in early days of Windows Phone but workarounds existed. Ideally, the API should use compression by default but it doesn’t.

Clarification

The HttpClient I mentioned above is for Windows Phone 7.x and 8.x apps using Silverlight not WinRT. The .NET stack has had multiple APIs for making web request overtime but HttpClient is the one everyone should be using now which is wrapper/replacement for all other HTTP APIs in .NET framework.

Starting with WinRT which is used for developing “universal” apps, there is a separate HttpClient API. This seems to be using compression by default but please verify that it is. Here is a good starting point for HttpClient in WinRT and samples. If this all seems very confusing, you are not alone. The HTTP API in Microsoft world is a mystery wonderland of confusion so ask if you have questions.

Implementation

Using compression in your app is extremely simple and quick as explained by the framework team. When you create an instance of HttpClient class, send an instance of HttpClientHandler in constructor with appropriate setup and you are done. All http requests sent using this instance will now send correct request header and automatically un-compress the response.

var handler = new HttpClientHandler();
if (handler.SupportsAutomaticDecompression)
{
    handler.AutomaticDecompression = DecompressionMethods.GZip |
                                     DecompressionMethods.Deflate;
}

var client = new HttpClient(handler);

 

Performance Tip

While you are at it, here is another performance tip. When you are downloading data from internet and deserializing it, instead of first storing response as a string and then parsing it, parse data directly from the response stream. This works seamlessly for JSON as well as XML content.

For JSON, JSON.NET supports deserializing data from stream. It’s not as obvious as deserializing from a string though. Using the HttpClient instance we created above, here is a code snippet to deserialize response stream.

try
{
    using (var stream = await httpClient.GetStreamAsync(url))
    {
        using (var streamReader = new StreamReader(stream))
        {
            using (var textReader = new JsonTextReader(streamReader))
            {
                var serializer = new JsonSerializer();
                var data = serializer.Deserialize<List<Entry>>(textReader);
            }
        }
    }
}
catch (ObjectDisposedException ex)
{
    // ignore this exception as stream gets closed somehow and "using" block tries to dispose it again
    Debug.WriteLine(ex);
}

For XML response, XDocument supports parsing streams directly.

using (var stream = await httpClient.GetStreamAsync(url))
{
    XDocument.Load(stream);
}

For using stream with JSON.NET, I came across an issue though. As I am using “using” constructs to ensure the resources get cleaned up, the stream gets closed twice which causes an exception. To workaround that, ignore ObjectDisposedException exception as I have done above.

One drawback of using compression is that the phone will have to spend some CPU cycles to uncompress data. With today’s phones though, this is negligible. There is no reason to not use compression in your apps.

Hope this helps.

image credit: wpcentral

Advertisements

2 thoughts on “Using gzip compression when making HTTP requests in Windows Phone apps

  1. hello there. Could you please elaborate on why/if the last performance tip is better than the following approach?
    using (HttpResponseMessage response = await _client.GetAsync(resourceUrl))
    {
    string jsonContent = await response.Content.ReadAsStringAsync();
    MyType data = JsonConvert.DeserializeObject(jsonContent);
    }
    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s