Is there a possible to add sync.Pool to io.copyBuffer

104 views
Skip to first unread message

qing...@gmail.com

unread,
May 21, 2020, 12:26:18 AM5/21/20
to golang-nuts
Hi all:
I write a simpile HTTP proxy,and find the most alloctions appear in io.copyBuffer

(pprof) list io.copyBuffer
Total: 2.80TB
ROUTINE ======================== io.copyBuffer in /usr/local/go/src/io/io.go
    1.03TB     2.47TB (flat, cum) 88.16% of Total
         .          .    383:   if wt, ok := src.(WriterTo); ok {
         .          .    384:           return wt.WriteTo(dst)
         .          .    385:   }
         .          .    386:   // Similarly, if the writer has a ReadFrom method, use it to do the copy.
         .          .    387:   if rt, ok := dst.(ReaderFrom); ok {
         .     3.02GB    388:           return rt.ReadFrom(src)
         .          .    389:   }
         .          .    390:   if buf == nil {
         .          .    391:           size := 32 * 1024
         .          .    392:           if l, ok := src.(*LimitedReader); ok && int64(size) > l.N {
         .          .    393:                   if l.N < 1 {
         .          .    394:                           size = 1
         .          .    395:                   } else {
         .          .    396:                           size = int(l.N)
         .          .    397:                   }
         .          .    398:           }
    1.03TB     1.03TB    399:           buf = make([]byte, size)
         .          .    400:   }
         .          .    401:   for {
         .     1.43TB    402:           nr, er := src.Read(buf)
         .          .    403:           if nr > 0 {
         .   569.57MB    404:                   nw, ew := dst.Write(buf[0:nr])
         .          .    405:                   if nw > 0 {
         .          .    406:                           written += int64(nw)
         .          .    407:                   }
         .          .    408:                   if ew != nil {
         .          .    409:                           err = ew

and this the stacktrace
0: 0 [2057907: 67433496576] @ 0x470169 0x6e508a 0x6e5042 0x6e4ca7 0x6cf82e 0x77bfe9 0x45f7a1
#       0x470168        io.copyBuffer+0x2a8                             /usr/local/go/src/io/io.go:399
#       0x6e5089        io.Copy+0x69                                    /usr/local/go/src/io/io.go:364
#       0x6e5041        net/http.(*transferWriter).doBodyCopy+0x21      /usr/local/go/src/net/http/transfer.go:400
#       0x6e4ca6        net/http.(*transferWriter).writeBody+0x426      /usr/local/go/src/net/http/transfer.go:348
#       0x6cf82d        net/http.(*Response).Write+0x42d                /usr/local/go/src/net/http/response.go:328
#       0x77bfe8        main.handler+0x318                              /root/ctrip/shendun/main.go:74
 

Ian Lance Taylor

unread,
May 21, 2020, 1:04:34 AM5/21/20
to qing...@gmail.com, golang-nuts
The data being copied is presumably coming from the Body field of your
*http.Response. If you set the Body field to a type that implements
the WriteTo method, and set the ContentLength field to the length of
the data, then you can do the write however you like.

Ian

qing...@gmail.com

unread,
May 21, 2020, 9:03:37 PM5/21/20
to golang-nuts
Thank you!  I change the code as your suggestion, it reduce 10% cpu usage.

在 2020年5月21日星期四 UTC+8下午1:04:34,Ian Lance Taylor写道:
Reply all
Reply to author
Forward
0 new messages