]> Cypherpunks repositories - gostls13.git/commitdiff
io: reduce allocations in Pipe constructor
authorJoe Tsai <joetsai@digital-static.net>
Sun, 5 Mar 2023 03:53:14 +0000 (19:53 -0800)
committerJoseph Tsai <joetsai@digital-static.net>
Thu, 17 Aug 2023 16:25:48 +0000 (16:25 +0000)
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>

src/io/pipe.go

index 2724e3f7abe4fddba4800b2ac7185ec66e031e0c..ae8322ee7b2f3a1a4845407a9a6122fef8ec9a5e 100644 (file)
@@ -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
 }