Back in 2012, I did an experiment to compare if and/or how much faster WebSockets are compared to AJAX (aka. XHR). It would be a "protocol benchmark" to see which way was faster to schlep data back and forth between a server and a browser in total. The conclusion of that experiment was that WebSockets were faster but when you take latency into account, the difference was minimal. Considering the added "complexities" of WebSockets (keeping connections, results don't come where the request was made, etc.) it's not worth it.
But, 7 years later browsers are very different. Almost all browsers that support JavaScript also support WebSockets. HTTP/2 might make things better too. And perhaps the WebSocket protocol is just better implemented in the browsers. Who knows? An experiment knows.
So I made a new experiment with similar tech. The gist of the code is best explained with some code:
loopXHR = async count => {
const res = await fetch(`/xhr?count=${count}`);
const data = await res.json();
const nextCount = data.count;
if (nextCount) {
this.loopXHR(nextCount);
} else {
this.endXHR();
}
};
Basically, pick a big number (e.g. 100) and send that integer to the server which does this:
count = self.get_argument("count")
data = {"count": int(count) - 1}
self.write(json.dumps(data))
So the browser keeps sending the number back to the server that decrements it and when the server returns 0
the loop ends and you look how long the whole thing took.
Try It
The code is here: https://github.com/peterbe/sockshootout2019
And the demo app is here: https://sockshootout.app
(Just press "Start!", wait and press it 2 or 3 more times)
Location, location, location
What matters is the geographical distance between you and the server. The server used in this experiment is in New York, USA.
What you'll find is that the closer you are to the server (lower latency) the better WebSocket performs. Here's what mine looks like:
My result between South Carolina, USA and New York, USA
Now, when I run the whole experiment all on my laptop the results look very different:
Running all locally
I don't have a screenshot for it but a friend of mine ran this from his location in Perth, Australia. There was no difference. If any difference it was "noise".
Same Conclusion?
Yes, latency matters most. The technique, for the benefit of performance, doesn't matter much.
No matter how fancy you're trying to be, what matters is the path the bytes have to travel. Or rather, the distance the bytes have to travel. If you're far away a large majority of the total time is sending and receiving the data. Not the time it takes the browser (or the server) to process it.
However, suppose you do have all your potential clients physically near the server, it might be beneficial to use WebSockets.
Thoughts and Conclusions
My original thought was to use WebSockets instead of XHR for an autocomplete widget. At almost every keystroke, you send it to the server and as search results come in, you update the search result display. Things like that need to be fast and "snappy". But that's not where WebSockets shine. They shine in their ability to actively await results without having a loop that periodically pulls. There's nothing wrong with WebSocket and it has its brilliant use cases.
In summary, don't bother just to get a single-digit percentage performance increase if the complexity of the code and infrastructure is non-trivial. Keep building cool stuff with WebSockets but if you expect one result per action, XHR is good enough.
Bonus
The experiment app does collect everyone's results (just the timings and IP) and I hope to find the time to process this and build graph a correlating the geographical distance compared to the difference between the two techniques. Watch this space!
By the way, if you do plan on writing some WebSocket implementation code I highly recommend Sockette. It's solid and easy to use.