Skip to content

proposal: io,net: add WriteMany interface #68625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Jorropo opened this issue Jul 29, 2024 · 5 comments
Open

proposal: io,net: add WriteMany interface #68625

Jorropo opened this issue Jul 29, 2024 · 5 comments
Labels
Milestone

Comments

@Jorropo
Copy link
Member

Jorropo commented Jul 29, 2024

Proposal Details

This proposal aims at making a user-implementable version of net.Buffers.

Add a new interface to io and implement it on net.* which implement net.buffersWriter:

type ManyWriter interface {
 // WriteMany has the same semantics as appending the buffers back to back into one buffer and calling [Writer.Write] method,
 // but it allows to remove the need to allocate and copy all the buffers in one contiguous memory region.
 // The implementation cannot write to any of the passed buffer or buffers slice.
 WriteMany(...[]byte) (n int64, err error)
}

note: this return int64 because it would be easy to build let's say 16GiB buffer on a 32bits pointer architecture by having the byte arrays alias each other.

(*net.Buffers).WriteTo would also check if the underlying implementation supports io.ManyWriter as well as net.buffersWriter.

@gopherbot gopherbot added this to the Proposal milestone Jul 29, 2024
@Jorropo Jorropo moved this to Incoming in Proposals Jul 29, 2024
@gabyhelp
Copy link

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

@Jorropo
Copy link
Member Author

Jorropo commented Jul 29, 2024

opening as a formal proposal to solve #21676, feel free to close a dup

@Jorropo Jorropo removed this from Proposals Jul 29, 2024
@Jorropo
Copy link
Member Author

Jorropo commented Jul 29, 2024

And in case of rehashing arguments from #21676 the problem I am seeing:
I have protocol with <small header> | <big payload> and a method like this:

func (*T) WritePayload(b []byte) error

Here are the possible solutions today and why they are not that good:

  1. Nagle's algorithm
    add latency in the pipeline, plus does not solve the double syscall overhead (with double digit Gbit/s TCP I have many profiles with >60% of time spent in syscall.Syscall6 doing TCP)
  2. net.Buffers
    it is not composable, in most of my usecases I have a TCPConn wrapped in TLS, HTTP or yamux.
  3. bufio.Writer
    still do two .Write call, the header is small enough to be fully buffered, then the payload is written to, it does not fit into the buffer, so bufio.Writer flushes the header and then pass the payload as-is in a second .Write call.
    • note: if we had such interface it would be useful to optimize this codepath so it use .WriteMany to write the buffered portion and the inbound payload in one call, would be done conditionally with a conditional type assertion but that would be a future proposal if something like this one passes.
  4. manually doing t.underlying.Write(append(header, payload...))
    generate garbage
  5. do solution 4 but store buffers in a receiver field and recycle them
    this double the memory usage of this one implementation / consumer pair and does not remove the cost of copying bytes around (worst CPU cache utilization)
  6. re-architecture the code to do dma style buffer access in callbacks (func (*T) WritePayload(n uint, func(dest []byte) error) error)
    create callback hell when composed and is not always possible (I don't always know the maximum size of the payload ahead of time)

@ianlancetaylor ianlancetaylor moved this to Incoming in Proposals Jul 29, 2024
@jfrech
Copy link

jfrech commented Aug 9, 2024

Does defining a dual io.ManyReader have any known applications?

@Jorropo
Copy link
Member Author

Jorropo commented Aug 9, 2024

@jfrech ManyReader ¿ not ManyWriter ?

Idk this is not this proposal feel free to open an other one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Incoming
Development

No branches or pull requests

4 participants