Skip to content

Commit 56076c3

Browse files
committed
io: reduce allocations in Pipe constructor
Rather than having PipeWriter and PipeReader a wrapper type on pipe, make them have the same underlying memory representation and rely instead of simply casting the same *pipe pointer as either a *PipeReader or *PipeWriter to control the set of methods. This reduces the number of allocations by 2, going from a total of 6 down to 4 allocations. Change-Id: I09207a00c4b7afb44c7773d752c5628a07e24fda Reviewed-on: https://go-review.googlesource.com/c/go/+/473535 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Joseph Tsai <[email protected]> Reviewed-by: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 469d9e2 commit 56076c3

File tree

1 file changed

+9
-13
lines changed

1 file changed

+9
-13
lines changed

src/io/pipe.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,15 @@ func (p *pipe) writeCloseError() error {
123123
}
124124

125125
// A PipeReader is the read half of a pipe.
126-
type PipeReader struct {
127-
p *pipe
128-
}
126+
type PipeReader struct{ pipe }
129127

130128
// Read implements the standard Read interface:
131129
// it reads data from the pipe, blocking until a writer
132130
// arrives or the write end is closed.
133131
// If the write end is closed with an error, that error is
134132
// returned as err; otherwise err is EOF.
135133
func (r *PipeReader) Read(data []byte) (n int, err error) {
136-
return r.p.read(data)
134+
return r.pipe.read(data)
137135
}
138136

139137
// Close closes the reader; subsequent writes to the
@@ -148,21 +146,19 @@ func (r *PipeReader) Close() error {
148146
// CloseWithError never overwrites the previous error if it exists
149147
// and always returns nil.
150148
func (r *PipeReader) CloseWithError(err error) error {
151-
return r.p.closeRead(err)
149+
return r.pipe.closeRead(err)
152150
}
153151

154152
// A PipeWriter is the write half of a pipe.
155-
type PipeWriter struct {
156-
p *pipe
157-
}
153+
type PipeWriter struct{ r PipeReader }
158154

159155
// Write implements the standard Write interface:
160156
// it writes data to the pipe, blocking until one or more readers
161157
// have consumed all the data or the read end is closed.
162158
// If the read end is closed with an error, that err is
163159
// returned as err; otherwise err is ErrClosedPipe.
164160
func (w *PipeWriter) Write(data []byte) (n int, err error) {
165-
return w.p.write(data)
161+
return w.r.pipe.write(data)
166162
}
167163

168164
// Close closes the writer; subsequent reads from the
@@ -178,7 +174,7 @@ func (w *PipeWriter) Close() error {
178174
// CloseWithError never overwrites the previous error if it exists
179175
// and always returns nil.
180176
func (w *PipeWriter) CloseWithError(err error) error {
181-
return w.p.closeWrite(err)
177+
return w.r.pipe.closeWrite(err)
182178
}
183179

184180
// Pipe creates a synchronous in-memory pipe.
@@ -197,10 +193,10 @@ func (w *PipeWriter) CloseWithError(err error) error {
197193
// Parallel calls to Read and parallel calls to Write are also safe:
198194
// the individual calls will be gated sequentially.
199195
func Pipe() (*PipeReader, *PipeWriter) {
200-
p := &pipe{
196+
pw := &PipeWriter{r: PipeReader{pipe: pipe{
201197
wrCh: make(chan []byte),
202198
rdCh: make(chan int),
203199
done: make(chan struct{}),
204-
}
205-
return &PipeReader{p}, &PipeWriter{p}
200+
}}}
201+
return &pw.r, pw
206202
}

0 commit comments

Comments
 (0)