Can HTTP/1 outperform HTTP/2?

2023-11-12

One of the benefits that HTTP/2 offers, is much fewer TCP connections that allow clients to fire multiple requests at once. This eliminates TCP overhead and makes the protocol faster. It’s common to do hundreds of requests over a single connection.

But, what if a TCP packet is lost? The reciver sends the previous ACK number to sender and the entire TCP connection is stucked till the lost packet is re-transmitted.

Naturally, re-transmittion is much faster for a single request rather than hundreds of them. This is well-known problem called “TCP head of line blocking” (HoL). As packet loss increases, HTTP/1 might theoriteccally outperform HTTP2 because HoL blocks much more packets (http requests).

Since I had linux around, it was quite easy to verify this theory by settings packet loss in the kernel.

tc is traffic-control utility used to configure the linux packet scheduler.

Using the tc we can set a desired packet loss for root queing discipline (qdisk) for local lo interface.

tc qdisc add dev lo root netem loss <n>

To unset loss just delete the setting:

tc qdisc del dev lo root netem loss

To execute perf test, I used k6 which does the job of getting network bussy. Moreover it provides metrics I am interested in.

I executed the test in the following manner:

for ((i = 0 ; i <= 10 ; i++)); do
    sudo tc qdisc add dev lo root netem loss ${i}%
    GODEBUG=http2client=0 k6 run --vus 100 --duration 60s --summary-export="${i}-loss_http1.1_summary.json" script.js
    GODEBUG=http2client=1 k6 run --vus 100 --duration 60s --summary-export="${i}-loss_http2_summary.json" script.js
    sudo tc qdisc del dev lo root netem
done

At the end just plot the summaries.

As we expected, HTTP2 performance got eventually worse accordingly with increasing packet loss.

Does it mean we should stick with HTTP/1.1? Definetely not! Networks are more reliable that it might seem and having this high packet loss is very unussual in common environments.

The HoL is “fixed” by HTTP/3 and QUIC.