WebSockets vs Oxygen.jl

I’m sure I’m doing something silly and wrong, I’m just not sure what.

In the following two MWE, a server is sending a 1 MB payload a hundrad times to one client, all within the same Julia session (v1.10.0 single thread).

The HTTP.WebSockets (HTTP v1.10.1) are performing 6 times worse than Oxygen.jl (v1.4.5), and I’m not sure why. I thought websockets were supposed to be faster than http requests…?

Here’s the websocket MWE:

using HTTP.WebSockets

const payload = Vector{UInt8}(undef, 10^6) # 1 MB

server = WebSockets.listen!("127.0.0.0", 8000) do ws
    for msg in ws
        send(ws, payload)
    end
end

n = 100
WebSockets.open("ws://127.0.0.0:8000") do ws
    send(ws, UInt8(1))
    t = @elapsed begin
        for (_, msg) in zip(1:n, ws)
            send(ws, UInt8(1))
        end
    end
    fps = n/t
    @show fps
end;

and here’s the oxygen one:

using Oxygen
using HTTP

const payload = Vector{UInt8}(undef, 10^6) # 1 MB

@get "/" function(req::HTTP.Request)
    binary(payload)
end

Threads.@spawn serve()

n = 100
t = @elapsed begin
    for i in 1:n
        HTTP.open("GET", "http://127.0.0.1:8080/") do io
            while !eof(io)
                read(io, 10^6)
            end
        end
    end
end
fps = n/t
@show fps

The benefit of WebSockets is a persistent bidirectional connection that should not experience latency to reconnect for many messages. By testing with both client and server or localhost, you bypass most network latency when reconnecting.

1 Like

But if reconnection-latency is absent in my setup for both websockets and http, then why would http be so much faster than websockets? I understand that reconnection-latency explains why the http version in my setup is faster than http out in the wild, but not why it should be faster than websockets.

I’ve now tested this further by putting the server part of the code on a Raspberry Pi. I then connected the RPI and my laptop (with the client part of the code) to the same router. In this configuration, the oxygen-http version still performed about three times faster than the websocket one.

Websocket performance optimization · Issue #1140 · JuliaWeb/HTTP.jl (github.com)

1 Like

In my case, adding

Sockets.nagle(ws.io.io, false)
Sockets.quickack(ws.io.io, true)

had no noticeable effect.