-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Closed
Description
It's not possible to Write to a *bufio.Writer without the []byte argument escaping, due
to the fast path passing p through an interface value:
package bufio
...
func (b *Writer) Write(p []byte) (nn int, err error) {
for len(p) > b.Available() && b.err == nil {
var n int
if b.Buffered() == 0 {
// Large write, empty buffer.
// Write directly from p to avoid copy.
n, b.err = b.wr.Write(p) // <------------ escapes
} else {
n = copy(b.buf[b.n:], p)
b.n += n
b.Flush()
}
nn += n
p = p[n:]
}
if b.err != nil {
return nn, b.err
}
n := copy(b.buf[b.n:], p)
b.n += n
nn += n
return nn, nil
}
Possible solutions:
0) do nothing. accept that it's not possible to have a caller do a small write from a
stack-local byte array. I don't like this option.
1) remove the fast path above. that's also sad, since it'd be worse in the common cases.
2) add a new public method on *bufio.Writer that's like Write, but without its p []byte
argument escaping. This is gross, because it's new API for a performance thing.
3) instead of passing p to b.wr.Write in the line of code labeled above, instead play a
game where we pass a copy of p if &p[0] is on the stack, otherwise pass p directly
(but this would probably involve gross unsafe tricks to avoid the compiler thinking that
p escapes)
4) caller can do a loop on its stack-local byte array and call WriteByte for each input.
this is what I've done so far.Reactions are currently unavailable