Open stokito opened 3 years ago
Does this optimization still apply when the net.Conn
is wrapped in a bufio.Writer
?
no, bufio is just a single array. It was added specifically for net.Conn
.
In the golang issues there is something like "net: Buffers makes multiple Write calls on Writers that don't implement buffersWriter"
The initial code was added in scope of "proposal: net: TCPConn supports Writev" issue.
That makes it very hard to use for us as we currently always wrap the net.Conn
in a bufio.Writer
. I think to fully make use of it we would also have to write the header into a []byte
and prepend it to the net.Buffers
so we can write everything at once.
If someone wants to make a pull request to make this all possible that would be great 😄
I've been looking into this and it seems challenging (==fun). It's inconvenient fasthttp's types export a public Write(w *bufio.Writer)
, because there is no way to extract the unwritten data (without copying them) from them for use with writev(2).
So I fear we need to clone all those methods to accept a custom buffer
type instead of bufio.Writer
and use those when no compression or TLS is used (because only then can we write straight to the file descriptor). I'm imagining the buffer
type to hold a [][]byte
, and the individual byte slices to be from a sync.Pool and always sized per Server.WriteBufferSize
.
My throughputbuffer library is almost exactly what we want, except that you can't add a []byte
without copying it in.
Drawbacks:
Given amount of efforts and additional complexity I'd rather closed the issue. But this can be used internally for headers + body. The headers are already stored in a slice.
The writev syscall similarly to sendfile can be used only for the raw HTTP but this can be used with kernel mod TLS. See Improving NGINX Performance with Kernel TLS and SSL_sendfile
P.S.
For me it looks like the ideal solution would be if the net.Buffers
merged into the bufio.Writer
.
They are naturally used in a similar way: make multiple writes and flush at once. Each writing can just append the slice instead of copying it. Unfortunately we can't change it because users (potentially) may change elements in a slice after writing.
A similar to the net.Buffers
is a Rope String.
In real life most of strings were created as result of at least one concatenation. Given that changing string to ropes might be huge deal.
The net.Buffers internally uses writev syscall so we can write multiple chunks without concatenation in buffer. This significantly improves performance and I wondered why fasthttp doesn't use it.