http/2 is much better than http for websites. It's very helpful if you have to make multiple http calls. But is there any significant benefit for a single call?
There are general considerations and specific considerations.
The general considerations is that HTTP/2, being a binary protocol, is much easier to implement and has many less corner cases than HTTP/1.1.
For example, the fact that HTTP/1.1 headers needs to parsed without knowing in advance header name length and header value length.
Another example is whether the HTTP/1.1 parser needs to support obsolete line folding in headers.
There are many many other corner cases in HTTP/1.1 header parsing that add additional complexity to the HTTP/1.1 parser that are just absent in HTTP/2 because it's a binary protocol and relies on HPack.
As for the specific considerations, there are two cases: a request that triggers also the opening of the connection, and a request that is made on an already opened connection.
In the first case HTTP/2 has additional processing to do with respect to HTTP/1.1.
TCP connection opening and TLS handshake being out of the picture (they are the same for HTTP/1.1 and HTTP/2), HTTP/2 requires sending a preface (to which the server must reply) before the first request, and this requires a tiny bit of additional processing.
The client preface and the request may be sent together; otherwise the request incurs in an additional roundtrip latency, waiting for the preface reply.
Upon the first request on a connection, HTTP/2 has no HPack state so that needs to be built. HTTP/1.1 has to parse the headers every time from scratch (char by char). I don't have data, but I think HTTP/2 has a slight edge here.
The second case, sending a request on an already opened connection, is probably favorable to HTTP/2 due to the fact that HPack has now "cached" a lot of headers, and so their parsing is basically reduced to just a lookup - whereas for HTTP/1.1 the header parsing must be done over and over for all requests.
This also means that subsequent HTTP/2 requests are much smaller than their HTTP/1.1 counterpart: a ~400 bytes HTTP/1.1 request is compressed down to a ~10 bytes HTTP/2 request.
For a single request this reduction does not play an important role as both requests will fit a single MTU; however, the game may change when many requests are being sent.
Data download (from server to client) has a slight overhead for HTTP/2 because each DATA
frame has a 9 octets overhead that may be absent in HTTP/1.1 (for downloads of known content length). The minimum overhead is typically 9 bytes over 16 KiB of data (the default HTTP/2 max frame size).
Data download in HTTP/2 is also subject to flow control, which may stall data download if the client is not smart/fast enough to send WINDOW_UPDATE
frames to the server.
The last consideration is about requests that uploads data to the server. It is important that the server is configured to enlarge the session and stream flow control window, because the default values are really small and will hurt data upload performance a lot.
In summary, I don't think that for a single request over the network there are "significant" benefits.
For example in Jetty (disclaimer, I am a committer) and therefore in Java, request processing is in the order of 10s-100s microseconds on my laptop.
Maybe there is a difference in that HTTP/1.1 or HTTP/2 is few microseconds faster or slower, but this will be completely obliterated by the network latency, so that you won't see any difference between a request made with HTTP/1.1 and one made with HTTP/2 in terms of response time.
There are so many variable that you can have when you say "HTTP request" that you have to benchmark a specific request to get an answer, and that answer may vary if you vary the request, if you vary the number of requests, if you vary whether the request has content or not, if you vary the response content length, etc.
I don't think there will be a big difference in case of a single request, because the same work has to be done with both HTTP/2 and HTTP/1.1 :
- make a TCP connection
- send the request
- server has to prepare / generate the response
- send the response back to client
- close the connection
So in both cases you'll have the same latency.
HTTP/2 however, uses compressed HTTP headers, which could add a small advantage if the header data is big, or with POST requests for example.
One of the main advantages of HTTP/2 is that multiple requests can be sent together, thereby reducing or even removing the latency between each request / response (on the same connection), so there is a much bigger gain when multiple files (or other data) are needed (loading a page, and retrieving the .css, .js and image files for example).
TL;DR: There are no benefits over HTTP/1.1 + TLS for a single request. Compared to HTTP 1.1 without encryption HTTP/2 has a 3k overhead mostly due to the server certificate.
Let's see.
Grabbing a small document from github with HTTP1.1 & TLS
$ curl --http1.1 -sv https://raw.githubusercontent.com/maban/styleguides/gh-pages/_resourceexample/airbnb.md 2>&1 > /dev/null | egrep 'data\]' | sed -e 's/ bytes data]//g' | sed -e 's/} \[/up\t/g' | sed -e 's/{ \[/down\t/g' | tee /dev/stderr | ruby -r yaml -r csv -e 'dict={"up"=>0, "down"=>0}; CSV.new(STDIN, col_sep: "\t").each { |r| dict[r
[0]]+=r[1].to_i }; puts dict.to_yaml'
up 5
up 512
down 122
down 25
down 3051
down 264
down 52
up 1
up 52
up 5
down 5
down 209
down 5
---
up: 575
down: 3733
This does not count the request header, response header and body, just the handshake protocol. But those stay the same across both HTTP versions.
Grabbing the same doc with http/2
$ curl --http2 -sv https://raw.githubusercontent.com/maban/styleguides/gh-pages/_resourceexample/airbnb.md 2>&1 > /dev/null | egrep 'data\]' | sed -e 's/ bytes data]//g' | sed -e 's/} \[/up\t/g' | sed -e 's/{ \[/down\t/g' | tee /dev/stderr | sort | ruby -r yaml -r csv -e 'dict={"up"=>0, "down"=>0}; CSV.new(STDIN, col_sep: "\t").each { |r| dict[r[0]]+=r[1].to_i }; puts dict.to_yaml'
up 5
up 512
down 122
down 19
down 3051
down 264
down 52
up 1
up 52
up 5
up 5
down 5
down 193
up 5
down 140
---
up: 585
down: 3846
http/2 looks a little bit larger. The handshake is pretty much the same. The biggest chunk is the server certificate that weighs in at 3k. There's 140 byte chunk at the end which is the body size. Could be an artefact in curl reporting but is negigible.
Grabbing the same document with HTTP1.1 without TLS
$ curl --http1.1 -sv http://raw.githubusercontent.com/maban/styleguides/gh-pages/_resourceexample/airbnb.md 2>&1 | egrep '^[><] ' | cut -c3-|tee /dev/stderr | wc
-c
GET /maban/styleguides/gh-pages/_resourceexample/airbnb.md HTTP/1.1
Host: raw.githubusercontent.com
User-Agent: curl/7.68.0
Accept: */*
HTTP/1.1 301 Moved Permanently
Connection: close
Content-Length: 0
Server: Varnish
Retry-After: 0
Location: https://raw.githubusercontent.com/maban/styleguides/gh-pages/_resourceexample/airbnb.md
Accept-Ranges: bytes
Date: Wed, 01 Feb 2023 00:51:54 GMT
Via: 1.1 varnish
X-Served-By: cache-ewr18172-EWR
X-Cache: HIT
X-Cache-Hits: 0
X-Timer: S1675212715.793392,VS0,VE0
Access-Control-Allow-Origin: *
Expires: Wed, 01 Feb 2023 00:56:54 GMT
Vary: Authorization,Accept-Encoding
633
Github serves a redirect but that's ok. The header size looks about the same. All we're missing is the body which we don't want to factor into the analysis.
So HTTP/2 overhead is about 3k larger than HTTP1/1 without encryption. In addition to that it costs a couple of extra round trips.
© 2022 - 2024 — McMap. All rights reserved.