uNetworking/uWebSockets.js

Query : Zero copy byte transfer

corporatepiyush opened this issue · 6 comments

Is it possible to achieve zero copy byte transfer (DMA) from

  1. disk to socket for static file serving
  2. pipe one websockets stream to another websockets stream

Or in other words, is it possible to have functionality similar to sendfile(2) and splice(2) linux native system calls ?

uasan commented

As far as I know, there is no such functionality, but I also really want it to implemented.

WebSockets are asymmetrical (client protocol is not the same as server protocol). So splice is not possible to use, unless you want to make some WebSocket proxy?.

Sendfile is possible to use, but is not built-in. Bun uses sendfile by sending the header of a HTTP response with uWS and then the remaining body with sendfile. This is possible with the HttpResponse::setWriteOffset to overwrite the assumed write offset when you are done with sendfile.

But for Node.js, none of this is built-in or planned or even wanted. There is no motivation to prioritize low level performance tweaks for Node.js for many reasons - one being that Node.js is so slow that it's the wrong fruit to reach for, or whatever the saying is (low hanging fruit first).

Other reasons are that uWebSockets is now close to 8 year old and has significant history and was designed before:

  • Spectre mitigations
  • kTLS
  • io_uring
  • QUIC

was known to the world. So there are some design properties that will not change in the Node.js version. Other reasons are that uWebSockets has always targeted small message sending where copies are negligible in fact copies are faster for small messages.

The C++ library will most likely get io_uring and possibly also kTLS, but these features are not planned for Node.js since Node.js is not even remotely as relevant as it was 8 years ago, and there are way better alternatives that pop up (such as Bun or even Deno). It's also quite impossible to integrate io_uring with Node.js efficiently, unlike epoll, without degrading performance.

So TLDR is; the C++ library is moving forwards with newer Linux-only features over time, but the Node.js variant still lacks any motivation whatsoever for any performance related stuff (there simply is no competition for Node.js - uWS is by far the fastest you can get for Node.js).

Thanks. Looking forward to new enhancement, hope they land soon.

uasan commented

Node.js is so slow that it's the wrong fruit to reach for, or whatever the saying is (low hanging fruit first).

The main reason to choose uWS.js is because it allows you not to use slow Node implementations.

Now sending a file requires the use of Node streams, the sendfile would allow you to go the fast way without using Node streams, solving problems in a fast path way fits perfectly into the ideology of the uWS.js

0x7d8 commented

compression may also fit into that then, like you could do res.setCompression()
if its set to auto uws decides what to use
and else you can set it to gzip, brotli or deflate

Possibly there could be res.endWithFile(f) as a built in at some point but it's very low prio