Most native mobile apps are “thin clients” — they need talk to backend API and fetch media resources over HTTP.
We wanted to reproduce CloudFlare HTTP2 browser demo as native iOS 9 application and test it on WiFi, LTE / 3G.
The test is to fetch 200 image tiles from an HTTP/1.1 capable server, and then repeat for HTTP/2 capable server.
HTTP/2 demonstrated to be consistently faster then HTTP/1.1 on this test
- 4 times faster on WiFi / 20Mbps cable, average server ping 50ms
- 6 times faster on LTE network, average server ping 90ms
- 15 times faster on 3G network, average server ping 120ms
- 2 times faster on 2G network, average server ping 400ms
The reason HTTP/2 is just 2x faster on 2G network is due to EDGE bandwidth constraints as at 170Kbps link rapidly saturates.
- Single active request per TCP connection
- iOS network stack maintains maximum of 4 TCP connections to the server, and multiplexes logical requests between them.
Therefore, a maximum of 4 simultaneous requests could be processed at any given moment in time, resulting in poor network link utilization and two main issues
- Server is unaware about next client needs until client fully consumed response to preceding request and delivered the following request
- If some responses are slow, they’ll block the connection
NB: one should not try to raise the number of concurrent TCP connections, as exceeding 5–7 max concurrent TCP sessions per individual client-server IP address/port combination may trigger anti-DDoS filters on some ISPs.
How is HTTP/2 different?
- Single TCP connection is maintained between client and server
- Logical HTTP requests are multiplexed over this single connection, and there is no limit how many concurrent requests client can send
- Binary protocol with efficient header compression
When iOS needs to fetch 200 images, instead of sequentially requesting them, it is able request all of them at once, and consume responses as they come.
Priorities and cancellations
Note how different the image tile render is:
- HTTP/1.1 requests are naturally fetched one by one making
- HTTP/2 requests are coming at seemingly random pattern, as all requests were given same priority
HTTP/2 defines request priorities and supports cancellations, so that if an application needs to render i.e. a dynamic gallery preview it can request high priority images for the initial view, request images down the list and i.e. cancel their download if user would navigate away or scroll deep down the list.
However it looks like that priorities are not yet supported in NSUrlSession (tested on iOS 9.2).
Link latency matters
The reason HTTP/2 massively outperformed HTTP/1.1 transfer is due to overheads introduced by link latency.
Each new connection involves 1 round-trip network datagram exchange between client and server to establish TCP connection, followed by 1–2 round trip datagram exchange for Transport Layer Security TLS handshake — two pre-requisites for HTTPS connection being established.
Because of that, even keeping aside unavoidable overheads such as DNS server name resolution and waking up radio interface into active transmit state, establishing a single HTTPS connection may cost several hundred milliseconds. HTTP/1.1 bears additional overhead by loosing time on extra connection handshakes in order to maintain connection pool for concurrent request execution.
Despite global LTE rollout, users worldwide still get a significant % of service on 3G/2G networks with higher latency compared to LTE