Skip to content

bufio: Writer.Writer's []byte argument escapes #5492

@bradfitz

Description

@bradfitz
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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions