Consider that the websockets are persistent connections it isn't all that unusual.. I think the overhead is in the http transaction.
The flow for device commands (http & Hubitat websocket) looks similar to this crude example..
[send hub] event fires -> call HubConnect eventHandler() -> call URLEncode() on event data -> call asyncHttpGet() ----> establish TCP session -> transfer data --> [receive hub] ACK/FIN --> teardown TCP session --> http request parsed & routed by hub -> call HubConnect mapping() -> call URLDecode() on event data -> execute device command()
With the HubConnect server the same flow looks like this since the socket is established and persistent...
[send hub] event fires -> call HubConnect eventHandler() -> call hcsSendMessage() -> call JsonOutput.toJson() -> webSocket.sendMessage() ----> [receive hub] data received & parse() called -> parseJson() event data -> execute device command()
I have no doubt the size of my system (555 devices) comes in to play as there's 2-3 events per second even after deduplication hitting the server hub.