diff options
author | Joe Tsai <joetsai@digital-static.net> | 2023-03-04 19:53:14 -0800 |
---|---|---|
committer | Joseph Tsai <joetsai@digital-static.net> | 2023-08-17 16:25:48 +0000 |
commit | 56076c3080022f595541932fb4cea379939ec313 (patch) | |
tree | 98daea6aae1028ccf36a8be41ef7ae2efe352bf3 /src/io | |
parent | 469d9e26eec76341da8ebc4ef9cedb5bdb32ce73 (diff) | |
download | go-56076c3080022f595541932fb4cea379939ec313.tar.gz go-56076c3080022f595541932fb4cea379939ec313.zip |
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 <iant@google.com>
Run-TryBot: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/io')
-rw-r--r-- | src/io/pipe.go | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/src/io/pipe.go b/src/io/pipe.go index 2724e3f7ab..ae8322ee7b 100644 --- a/src/io/pipe.go +++ b/src/io/pipe.go @@ -123,9 +123,7 @@ func (p *pipe) writeCloseError() error { } // A PipeReader is the read half of a pipe. -type PipeReader struct { - p *pipe -} +type PipeReader struct{ pipe } // Read implements the standard Read interface: // it reads data from the pipe, blocking until a writer @@ -133,7 +131,7 @@ type PipeReader struct { // If the write end is closed with an error, that error is // returned as err; otherwise err is EOF. func (r *PipeReader) Read(data []byte) (n int, err error) { - return r.p.read(data) + return r.pipe.read(data) } // Close closes the reader; subsequent writes to the @@ -148,13 +146,11 @@ func (r *PipeReader) Close() error { // CloseWithError never overwrites the previous error if it exists // and always returns nil. func (r *PipeReader) CloseWithError(err error) error { - return r.p.closeRead(err) + return r.pipe.closeRead(err) } // A PipeWriter is the write half of a pipe. -type PipeWriter struct { - p *pipe -} +type PipeWriter struct{ r PipeReader } // Write implements the standard Write interface: // it writes data to the pipe, blocking until one or more readers @@ -162,7 +158,7 @@ type PipeWriter struct { // If the read end is closed with an error, that err is // returned as err; otherwise err is ErrClosedPipe. func (w *PipeWriter) Write(data []byte) (n int, err error) { - return w.p.write(data) + return w.r.pipe.write(data) } // Close closes the writer; subsequent reads from the @@ -178,7 +174,7 @@ func (w *PipeWriter) Close() error { // CloseWithError never overwrites the previous error if it exists // and always returns nil. func (w *PipeWriter) CloseWithError(err error) error { - return w.p.closeWrite(err) + return w.r.pipe.closeWrite(err) } // Pipe creates a synchronous in-memory pipe. @@ -197,10 +193,10 @@ func (w *PipeWriter) CloseWithError(err error) error { // Parallel calls to Read and parallel calls to Write are also safe: // the individual calls will be gated sequentially. func Pipe() (*PipeReader, *PipeWriter) { - p := &pipe{ + pw := &PipeWriter{r: PipeReader{pipe: pipe{ wrCh: make(chan []byte), rdCh: make(chan int), done: make(chan struct{}), - } - return &PipeReader{p}, &PipeWriter{p} + }}} + return &pw.r, pw } |