Websocket: рдЬрдм рд╕рдВрдкреАрдбрд╝рди рдЪрд╛рд▓реВ рд╣реЛ, рддреЛ рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдореЗрдВ рд╡реГрджреНрдзрд┐

рдХреЛ рдирд┐рд░реНрдорд┐рдд 11 рдЬрдире░ 2017  ┬╖  50рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: gorilla/websocket

рдирдорд╕реНрддреЗ,

рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реЗ рд╕рдкреНрддрд╛рд╣ Centrifugo рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рд╣реИред
рдореИрдВ рдХрдЪреНрдЪреЗ рд╡реЗрдмрд╕реЛрдХреЗрдЯ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬреЛ рд╣реБрдб рдХреЗ рдиреАрдЪреЗ рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред

рдореБрдЭреЗ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдкреНрд░рддрд┐-рд╕рдВрджреЗрд╢-рдЕрдкрд╕реНрдлреАрддрд┐ рд╕рдХреНрд╖рдо рд╣реИ, рдмрд╣реБрдд рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП docker рдХрдВрдЯреЗрдирд░ рдХреНрд░реИрд╢ рдмрд┐рдВрджреБ рддрдХ рд╕реНрдореГрддрд┐ рдореЗрдВ рднрд╛рд░реА рд╡рд┐рдХрд╛рд╕ рд╣реЛрддрд╛ рд╣реИред

рдореИрдВ рдПрдХ рдбреЙрдХрдЯрд░ рдХрдВрдЯреЗрдирд░ рдХреЗ рдЕрдВрджрд░ рдЪрд▓ рд░рд╣рд╛ рд╣реВрдВ, рдФрд╕рдд 150K-200K рд╕рдорд╡рд░реНрддреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде, рдореЗрд░реА рдФрд╕рдд рд╕рдВрджреЗрд╢ рджрд░ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 30K-50K рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рдмреАрдЪ, 600 рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдФрд╕рдд рд╕рдВрджреЗрд╢ рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╣реИред

рдкреНрд░рддрд┐-рд╕рдВрджреЗрд╢-рд╡рд┐рдХреНрд╖реЗрдк рдХреЗ рдмрд┐рдирд╛ рдХреЛрдИ рдореЗрдореЛрд░реА рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдмрдврд╝рддреА рд╣реИ рдФрд░ рдкреНрд░рджрд░реНрд╢рди рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИред

рдХреНрдпрд╛ рдХреЛрдИ рдореБрдЭреЗ рдЗрд╕рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ?

рдзрдиреНрдпрд╡рд╛рджред

bug help wanted question waiting on new maintainer

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдореИрдВрдиреЗ рдЧреЛрд▓рдВрдЧ рджрд╛рдпрд░ рдХрд┐рдпрд╛ рд╣реИ / # 32371 рдЬрд╛рдУ

рд╕рднреА 50 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдкрд╣рд▓рд╛ рдХрджрдо рд╢рд╛рдпрдж рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдХрд╛ рдПрдХ рдвреЗрд░ рдФрд░ рдЖрд╡рдВрдЯрди рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реЛрдЧрд╛ рдЬреЛ рдХрд┐ рдкреАрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИред

рдХреГрдкрдпрд╛ рдкреИрдХреЗрдЬ рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдкреНрд░реЛрдлрд╛рдЗрд▓ рддреИрдпрд╛рд░ рдХрд░реЗрдВред рдкреВрд▓ рдлрд╝реНрд▓реЛрдЯ рдкрд╛рдардХреЛрдВ рдХреЗ рд▓рд┐рдП рд╣рд╛рд▓рд┐рдпрд╛ рдмрджрд▓рд╛рд╡ рдФрд░ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред

рдзрдиреНрдпрд╡рд╛рдж рджреЛрд╕реНрддреЛрдВ,

рдореИрдВ Centrifugo рдХреЗ рдЕрдЧрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬрд┐рд╕рдореЗрдВ рдЖрдкрдХрд╛ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рд╢рд╛рдорд┐рд▓ рд╣реИ рдФрд░ рдлрд┐рд░ рдЖрд╡реЗрджрди рдХреЛ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХрд░реЗрдЧрд╛ рдФрд░ рдпрд╣рд╛рдВ рдЕрдкрд▓реЛрдб рдХрд░реЗрдЧрд╛ред

рдЖрдк рддрдм рддрдХ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЖрдЬ рдпрд╛ рдХрд▓ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рд╣реЛрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЖрдкрдХреЗ рдКрдкрд░ рд╣реИред

рдпрд╣рд╛рдВ рдкрд░ рдкрд┐рдкрд░рдореЗрдВрдЯ рдбрдВрдк рд╣реИ

рдпрд╣ рдвреЗрд░ рдкреНрд░реЛрдлрд╛рдЗрд▓ рд╣реИ

@kisielk @garyburd рдореИрдВрдиреЗ

https://gist.github.com/joshdvir/091229e3d3e4ade8d73b8cffe86c602b

рдореИрдВрдиреЗ рдЙрддреНрдкрд╛рджрди рдиреЛрдб рд╕реЗ рд╕реАрдкреАрдпреВ рдФрд░ рдореЗрдореЛрд░реА рдкреНрд░реЛрдлрд╛рдЗрд▓ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП @ рдЬреЛрд╢рд╡реАрд░ рд╕реЗ рдкреВрдЫрд╛, рдпрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ:

CPU:

(pprof) top 20 --cum
28.99s of 62.03s total (46.74%)
Dropped 523 nodes (cum <= 0.31s)
Showing top 20 nodes out of 155 (cum >= 8.07s)
      flat  flat%   sum%        cum   cum%
         0     0%     0%     58.68s 94.60%  runtime.goexit
     0.05s 0.081% 0.081%     45.44s 73.25%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessages
     0.16s  0.26%  0.34%     44.23s 71.30%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessage
     0.16s  0.26%   0.6%     44.07s 71.05%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*wsSession).Send
     0.05s 0.081%  0.68%     43.82s 70.64%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).WriteMessage
     0.01s 0.016%  0.69%     21.67s 34.93%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*flateWriteWrapper).Close
     0.03s 0.048%  0.74%     20.19s 32.55%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).NextWriter
     0.07s  0.11%  0.85%     19.79s 31.90%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.compressNoContextTakeover
    17.56s 28.31% 29.16%     17.56s 28.31%  runtime.memclr
     0.04s 0.064% 29.23%     15.46s 24.92%  compress/flate.(*Writer).Reset
     0.03s 0.048% 29.28%     15.42s 24.86%  compress/flate.(*compressor).reset
         0     0% 29.28%     14.40s 23.21%  compress/flate.(*Writer).Flush
         0     0% 29.28%     14.40s 23.21%  compress/flate.(*compressor).syncFlush
     2.62s  4.22% 33.50%     14.01s 22.59%  compress/flate.(*compressor).deflate
     0.01s 0.016% 33.52%     11.05s 17.81%  compress/flate.(*compressor).writeBlock
     0.15s  0.24% 33.76%     11.04s 17.80%  compress/flate.(*huffmanBitWriter).writeBlock
     0.21s  0.34% 34.10%      9.05s 14.59%  runtime.systemstack
     0.06s 0.097% 34.19%      8.87s 14.30%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*messageWriter).flushFrame
     0.07s  0.11% 34.31%      8.81s 14.20%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).write

WriteMessage рдореЗрдВ рдмрд┐рддрд╛рдП рдЧрдП рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕реАрдкреАрдпреВ:

(pprof) list WriteMessage
Total: 1.03mins
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).WriteMessage in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/conn.go
      50ms     43.82s (flat, cum) 70.64% of Total
         .          .    659:
         .          .    660:// WriteMessage is a helper method for getting a writer using NextWriter,
         .          .    661:// writing the message and closing the writer.
         .          .    662:func (c *Conn) WriteMessage(messageType int, data []byte) error {
         .          .    663:
      50ms       50ms    664:   if c.isServer && (c.newCompressionWriter == nil || !c.enableWriteCompression) {
         .          .    665:
         .          .    666:       // Fast path with no allocations and single frame.
         .          .    667:
         .       20ms    668:       if err := c.prepWrite(messageType); err != nil {
         .          .    669:           return err
         .          .    670:       }
         .          .    671:       mw := messageWriter{c: c, frameType: messageType, pos: maxFrameHeaderSize}
         .       10ms    672:       n := copy(c.writeBuf[mw.pos:], data)
         .          .    673:       mw.pos += n
         .          .    674:       data = data[n:]
         .      1.69s    675:       return mw.flushFrame(true, data)
         .          .    676:   }
         .          .    677:
         .     20.19s    678:   w, err := c.NextWriter(messageType)
         .          .    679:   if err != nil {
         .          .    680:       return err
         .          .    681:   }
         .      190ms    682:   if _, err = w.Write(data); err != nil {
         .          .    683:       return err
         .          .    684:   }
         .     21.67s    685:   return w.Close()
         .          .    686:}

NextWriter:

(pprof) list NextWriter
Total: 1.03mins
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).NextWriter in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/conn.go
      30ms     20.19s (flat, cum) 32.55% of Total
         .          .    437:// method flushes the complete message to the network.
         .          .    438://
         .          .    439:// There can be at most one open writer on a connection. NextWriter closes the
         .          .    440:// previous writer if the application has not already done so.
         .          .    441:func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) {
         .       90ms    442:   if err := c.prepWrite(messageType); err != nil {
         .          .    443:       return nil, err
         .          .    444:   }
         .          .    445:
         .          .    446:   mw := &messageWriter{
         .          .    447:       c:         c,
         .          .    448:       frameType: messageType,
      10ms      280ms    449:       pos:       maxFrameHeaderSize,
         .          .    450:   }
         .       10ms    451:   c.writer = mw
         .          .    452:   if c.newCompressionWriter != nil && c.enableWriteCompression && isData(messageType) {
      10ms     19.80s    453:       w := c.newCompressionWriter(c.writer)
         .          .    454:       mw.compress = true
      10ms       10ms    455:       c.writer = w
         .          .    456:   }
         .          .    457:   return c.writer, nil
         .          .    458:}
         .          .    459:
         .          .    460:type messageWriter struct {

compressNoContextTakeover:

(pprof) list compressNoContextTakeover
Total: 1.03mins
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.compressNoContextTakeover in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/compression.go
      70ms     19.79s (flat, cum) 31.90% of Total
         .          .     33:   fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil)
         .          .     34:   return &flateReadWrapper{fr}
         .          .     35:}
         .          .     36:
         .          .     37:func compressNoContextTakeover(w io.WriteCloser) io.WriteCloser {
         .      130ms     38:   tw := &truncWriter{w: w}
      40ms      3.93s     39:   fw, _ := flateWriterPool.Get().(*flate.Writer)
      10ms     15.47s     40:   fw.Reset(tw)
      20ms      260ms     41:   return &flateWriteWrapper{fw: fw, tw: tw}
         .          .     42:}

рдФрд░ рдЕрдм рдвреЗрд░ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓:

(pprof) top 30 --cum
4794.23MB of 5414.45MB total (88.55%)
Dropped 238 nodes (cum <= 27.07MB)
Showing top 30 nodes out of 46 (cum >= 113.64MB)
      flat  flat%   sum%        cum   cum%
         0     0%     0%  5385.39MB 99.46%  runtime.goexit
         0     0%     0%  4277.82MB 79.01%  sync.(*Pool).Get
         0     0%     0%  4277.82MB 79.01%  sync.(*Pool).getSlow
         0     0%     0%  4182.80MB 77.25%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessages
         0     0%     0%  4181.80MB 77.23%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessage
         0     0%     0%  4181.80MB 77.23%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*wsSession).Send
         0     0%     0%  4181.80MB 77.23%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).WriteMessage
       8MB  0.15%  0.15%  4168.27MB 76.98%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).NextWriter
      12MB  0.22%  0.37%  4160.27MB 76.84%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.compressNoContextTakeover
 3792.80MB 70.05% 70.42%  4148.27MB 76.61%  compress/flate.NewWriter
         0     0% 70.42%  4148.27MB 76.61%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.glob..func1
    0.50MB 0.0092% 70.43%  1156.29MB 21.36%  net/http.(*conn).serve
         0     0% 70.43%   873.42MB 16.13%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*HTTPServer).Logged.func1
         0     0% 70.43%   873.42MB 16.13%  net/http.HandlerFunc.ServeHTTP
         0     0% 70.43%   872.92MB 16.12%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*HTTPServer).WrapShutdown.func1
         0     0% 70.43%   872.92MB 16.12%  net/http.(*ServeMux).ServeHTTP
         0     0% 70.43%   872.92MB 16.12%  net/http.serverHandler.ServeHTTP
         0     0% 70.43%   866.91MB 16.01%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*HTTPServer).RawWebsocketHandler
         0     0% 70.43%   866.91MB 16.01%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*HTTPServer).RawWebsocketHandler-fm
         0     0% 70.43%   404.78MB  7.48%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).ReadMessage
  355.47MB  6.57% 76.99%   355.47MB  6.57%  compress/flate.(*compressor).init
         0     0% 76.99%   320.19MB  5.91%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Upgrader).Upgrade
    0.50MB 0.0092% 77.00%   292.64MB  5.40%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).NextReader
    1.50MB 0.028% 77.03%   291.64MB  5.39%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.decompressNoContextTakeover
  215.85MB  3.99% 81.02%   216.35MB  4.00%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.newConn
  159.10MB  2.94% 83.96%   159.10MB  2.94%  compress/flate.(*decompressor).Reset
  129.04MB  2.38% 86.34%   129.04MB  2.38%  compress/flate.NewReader
         0     0% 86.34%   129.04MB  2.38%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.glob..func2
  119.46MB  2.21% 88.55%   119.46MB  2.21%  net/http.newBufioWriterSize
         0     0% 88.55%   113.64MB  2.10%  io/ioutil.ReadAll

NextWriter:

(pprof) list WriteMessage
Total: 5.29GB
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).WriteMessage in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/conn.go
         0     4.08GB (flat, cum) 77.23% of Total
         .          .    673:       mw.pos += n
         .          .    674:       data = data[n:]
         .          .    675:       return mw.flushFrame(true, data)
         .          .    676:   }
         .          .    677:
         .     4.07GB    678:   w, err := c.NextWriter(messageType)
         .          .    679:   if err != nil {
         .          .    680:       return err
         .          .    681:   }
         .          .    682:   if _, err = w.Write(data); err != nil {
         .          .    683:       return err
         .          .    684:   }
         .    13.53MB    685:   return w.Close()
         .          .    686:}

compressNoContextTakeover:

(pprof) list compressNoContextTakeover
Total: 5.29GB
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.compressNoContextTakeover in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/compression.go
      12MB     4.06GB (flat, cum) 76.84% of Total
         .          .     33:   fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil)
         .          .     34:   return &flateReadWrapper{fr}
         .          .     35:}
         .          .     36:
         .          .     37:func compressNoContextTakeover(w io.WriteCloser) io.WriteCloser {
      10MB       10MB     38:   tw := &truncWriter{w: w}
         .     4.05GB     39:   fw, _ := flateWriterPool.Get().(*flate.Writer)
         .          .     40:   fw.Reset(tw)
       2MB        2MB     41:   return &flateWriteWrapper{fw: fw, tw: tw}
         .          .     42:}

@FZambia рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдЬрд╛рдирдХрд╛рд░реА рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

рдкреВрд▓ рдХрд┐рддрдирд╛ рдкреНрд░рднрд╛рд╡реА рд╣реИ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдВ рдФрд░ рдпрд╣рд╛рдВ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╢рд╛рдпрдж рд╡рд╣рд╛рдБ рдПрдХ рдХреЛрдб рдкрде рд╣реИ рдЬрд╣рд╛рдБ рдлрд╝реНрд▓реИрдЯ рд▓реЗрдЦрдХ рдХреЛ рдкреВрд▓ рдореЗрдВ рдирд╣реАрдВ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд╕рдВрднрд╡рддрдГ рд╕рдВрдмрдВрдзрд┐рдд: https://github.com/golang/go/issues/18625

@ y3llowcake рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдЗрд╢рд╛рд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

рдореИрдВрдиреЗ рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рд╡реЗрдмрд╕реИрдЯ рдХреЗ рд▓рд┐рдП рдЯреЗрд╕реНрдЯ рдХреЗрд╕ рд▓рд┐рдЦрд╛ рд╣реИ:

type testConn struct {
    conn     *Conn
    messages chan []byte
}

func newTestConn(c *Conn, bufferSize int) *testConn {
    return &testConn{
        conn:     c,
        messages: make(chan []byte, bufferSize),
    }
}

func printss() {
    m := runtime.MemStats{}
    runtime.ReadMemStats(&m)
    fmt.Printf("inuse: %d sys: %d\n", m.StackInuse, m.StackSys)
}

func TestWriteWithCompression(t *testing.T) {
    w := ioutil.Discard
    done := make(chan struct{})
    numConns := 1000
    numMessages := 1000
    conns := make([]*testConn, numConns)
    var wg sync.WaitGroup
    for i := 0; i < numConns; i++ {
        c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024)
        c.enableWriteCompression = true
        c.newCompressionWriter = compressNoContextTakeover
        conns[i] = newTestConn(c, 256)
        wg.Add(1)
        go func(c *testConn) {
            defer wg.Done()
            i := 0
            for i < numMessages {
                select {
                case <-done:
                    return
                case msg := <-c.messages:
                    c.conn.WriteMessage(TextMessage, msg)
                    i++
                }
            }
        }(conns[i])
    }
    messages := textMessages(100)
    for i := 0; i < numMessages; i++ {
        if i%100 == 0 {
            printss()
        }
        msg := messages[i%len(messages)]
        for _, c := range conns {
            c.messages <- msg
        }
    }
    wg.Wait()
}

func textMessages(num int) [][]byte {
    messages := make([][]byte, num)
    for i := 0; i < num; i++ {
        msg := fmt.Sprintf("planet: %d, country: %d, city: %d, street: %d", i, i, i, i)
        messages[i] = []byte(msg)
    }
    return messages
}

рдпрд╣ рд╕рдВрдкреАрдбрд╝рди рд╕рдХреНрд╖рдо рдХреЗ рд╕рд╛рде 1000 рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рддрд╛ рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдмрдлрд░ рдореИрд╕реЗрдЬ рдЪреИрдирд▓ рдХреЗ рд╕рд╛рде рд╣реИред рдлрд┐рд░ рдПрдХ рд▓реВрдк рдореЗрдВ рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдореЗрдВ рд╕рдВрджреЗрд╢ рд▓рд┐рдЦрддреЗ рд╣реИрдВред

рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрд╣ go1.7.4 рд╕рд╛рде рдХреИрд╕рд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИ

fz<strong i="7">@websocket</strong>: go test -test.run=TestWriteWithCompression
inuse: 4259840 sys: 4259840
inuse: 27394048 sys: 27394048
inuse: 246251520 sys: 246251520
inuse: 1048510464 sys: 1048510464
inuse: 1048510464 sys: 1048510464
inuse: 1049034752 sys: 1049034752
inuse: 1049034752 sys: 1049034752
inuse: 1049034752 sys: 1049034752
inuse: 1049034752 sys: 1049034752
inuse: 1049034752 sys: 1049034752
PASS
ok      github.com/gorilla/websocket    11.053s

рдкреНрд░рддрд┐рдмрджреНрдз рдХреЗ рд╕рд╛рде рдЬрд╛рдУ рдХрд╛ рдЙрдкрдпреЛрдЧ https://github.com/golang/go/commit/9c3630f578db1d4331b367c3c7d284db299be3a6

fz<strong i="12">@websocket</strong>: go1.8 test -test.run=TestWriteWithCompression
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
inuse: 4521984 sys: 4521984
PASS
ok      github.com/gorilla/websocket    12.023s

рд╣рд╛рд▓рд╛рдВрдХрд┐ рдлрд┐рд▓рд╣рд╛рд▓ рдпрд╣ рдХрд╣рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░реЗрдЧреА рдпрд╛ рдирд╣реАрдВред

рдореИрдВрдиреЗ рднреА flate https://github.com/klauspost/compress рдХреЗ рд╕рд╛рде @klauspost рджреНрд╡рд╛рд░рд╛ рдлрд╝рд┐рдХреНрд╕реЗрд╕ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:

fz<strong i="20">@websocket</strong>: go test -test.run=TestWriteWithCompression
inuse: 4358144 sys: 4358144
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
inuse: 4587520 sys: 4587520
PASS
ok      github.com/gorilla/websocket    3.426s

рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрд╕ рдлрд┐рдХреНрд╕ рдХреЗ рдмрд┐рдирд╛ рднреА https://github.com/klauspost/compress рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдмрд┐рдирд╛ рдореЗрдореЛрд░реА рдЧреНрд░реЛрде рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддреА рд╣реИ ... рдореИрдВ рдЗрд╕реЗ рд╕рдордЭрд╛ рдирд╣реАрдВ рд╕рдХрддрд╛ред

рдпрд╣рд╛рдВ рднреА https://github.com/klauspost/compress рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдкрд░рд┐рдгрд╛рдо рд╣реИ:

BenchmarkWriteWithCompression-4       200000          5676 ns/op         149 B/op          3 allocs/op

рдпрд╣ 4x рд╕реНрдкреАрдбрдЕрдк рд╣реИ, рдЬреЛ рдорд╛рдирдХ lib compress/flate рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╣реИ:

BenchmarkWriteWithCompression-4        50000         25362 ns/op         128 B/op          3 allocs/op

@ рдЧреИрд░реАрдмрд░реНрдб рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рдХреЛрд░ рдореЗрдВ рдЧреИрд░-рдорд╛рдирдХ

рдЙрд╕ рдлрд┐рдХреНрд╕ рдХреЗ рдмрд┐рдирд╛ рднреА [рдпрд╣] рдмрд┐рдирд╛ рдореЗрдореЛрд░реА рдмрдврд╝реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИ ... рдореИрдВ рдЗрд╕реЗ рд╕рдордЭрд╛ рдирд╣реАрдВ рд╕рдХрддрд╛ред

AFAICT, рдпрд╣ рдкреИрдХреЗрдЬ "рд╕реНрддрд░ 3" рд╕рдВрдкреАрдбрд╝рди (рдЬреЛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдореЗрд░реЗ рдкреИрдХреЗрдЬ рд╕реНрддрд░ рдореЗрдВ 1-4 рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╣реИ, рдФрд░ "рдЬреЗрдиреЗрд░рд┐рдХ" рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ, рдЬрд┐рд╕рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рд╣реИред

рдЧреЛ 1.7 рдХреЗ рд╕реНрддрд░ 1 (рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рдЧрддрд┐) рдореЗрдВ рдПрдХ рд╕рдорд╛рди рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрджрд┐ рдЖрдк рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдЕрдиреБрднрд╡ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдПрдХ рдРрд╕рд╛ рд╕рдорд╛рдзрд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдкреИрдХреЗрдЬ рдЖрдпрд╛рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ (рднрд▓реЗ рд╣реА рдореИрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд╡рд┐рдХрд▓реНрдк рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдмреБрд░рд╛ рди рдорд╛рдиреВрдБ)ред рд╕реНрддрд░ 1 рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд░реНрд╢рди рдореЗрд░реЗ рдкреИрдХреЗрдЬ рдХреЗ рдмрд╣реБрдд рдХрд░реАрдм рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

@klauspost рдХреЛ рд╕рдордЭрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдмрд╕ рдЖрдкрдиреЗ рдХреНрдпрд╛ рдХрд╣рд╛ - рд╣рд╛рдБ, рд╕рдореНрдкреАрдбрди рд╕реНрддрд░ 1 рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд╕рд╛рде рдЖрдкрдХреА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рддреБрд▓рдиреАрдп рд╣реИ рдФрд░ go1.7 рдореЗрдВ рдХреЛрдИ рд╕реНрдореГрддрд┐ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ (рдКрдкрд░ рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓реЗ рдореЗрдВ)

@ рдЧреИрд░реАрдмрд░реНрдб рдЖрдк рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рд╕реЛрдЪрддреЗ рд╣реИрдВ? рдореИрдВ рджреЛ рд╕рдорд╛рдзрд╛рди рджреЗрдЦрддрд╛ рд╣реВрдВ рдЬреЛ рд╣рдорд╛рд░реА рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ рдХреЗ рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдП рдЧрдП рдЪрд░ рдмрдирд╛рдПрдВ рдпрд╛ рдХрд╕реНрдЯрдо рдлреНрд▓реИрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдкреНрд▓рдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВред рдмреЗрд╢рдХ рд╣рдо go1.8 рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рд╕рдВрдкреАрдбрд╝рди рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдЕрднреА рднреА рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдХреНрдпрд╛ рдЖрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рджреА рдЧрдИ рд╕рд▓рд╛рд╣ рдХреЗ рд╕рд╛рде рдХрд╕реНрдЯрдо рдмрд┐рд▓реНрдб рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рдХреЙрдкреА рдХреЙрдкреА рдмрдЧ рджреЗрдЦреЗрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдХреИрд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИ?

@FZambia рдЕрдм рдПрдХ рдХреЗ рд▓рд┐рдП рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ? рдпрд╣ рд╢рд╛рдпрдж рдЗрд╕ рд╕рдордп рдЕрдзрд┐рдХрд╛рдВрд╢ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИ рдФрд░ рдЕрдзрд┐рдХ рдПрдкреАрдЖрдИ рд╕рддрд╣ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдиреЗ рд╕реЗ рдмрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИред

@garyburd рдореИрдВ рд╣реВрдВ , рд╕рдВрдкреАрдбрд╝рди рд╕реЗрдЯ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдиреЗ рд╕реЗ рдореЗрд░реЗ рд╡рд┐рд╢реЗрд╖ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдореЗрд░реЗ рдкрд╛рд╕ 200K рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 80K рд╕рдВрджреЗрд╢реЛрдВ рдХрд╛ рдПрдХ рдкреНрд░рд╢рдВрд╕рдХ рд╣реИ, рдЬреЛ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЯреНрд░реИрдлрд╝рд┐рдХ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИ, рдЕрдЧрд░ рдореИрдВ рд╕рдХреНрд╖рдо рд╣реЛрдКрдВрдЧрд╛ рдХрдореНрдкреНрд░реЗрд╢рди рд▓реЗрд╡рд▓ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВ рд╕рд░реНрд╡рд░ рдирдВрдмрд░реЛрдВ рдФрд░ рдЯреНрд░реИрдлрд╝рд┐рдХ рдХреЗ рдмреАрдЪ рдХрд╛ рдордзреБрд░ рд╕реНрдерд╛рди рдвреВрдВрдв рд╕рдХрддрд╛ рд╣реВрдБред
рдЖрдорддреМрд░ рдкрд░, рд╕рд░реНрд╡рд░ рдЯреНрд░реИрдлрд┐рдХ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдХрдо рдЦрд░реНрдЪ рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рдЯреНрд░реИрдлрд┐рдХ рдЗрддрдирд╛ рдЕрдзрд┐рдХ рд╣реЛрддрд╛ рд╣реИ рддреЛ рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ рд╣реЛрдЧрд╛
рдзрдиреНрдпрд╡рд╛рдж

рдареАрдХ рд╣реИ, рдЪрд▓реЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:

type CompressionOptions {
    // Level specifies the compression level for the flate compressor.  Valid levels range from
    // -2 to 9.  Level -2 will use Huffman compression only. Level -1 uses the default compression 
    // level.  Level 0 does not attempt any compression.  Levels 1 through 9 range from best
    // speed to best compression. 
    // 
    // Applications should set this field.  The default value of 0 does not attempt any compression.
    Level int
}

type Dialer struct {
   // CompressionOptions specifies options the client should use for 
   // per message compression (RFC 7692).  If CompressionOptions is nil and
   // EnableCompression is nil, then the client does not attempt to negotiate
   // compression with the server.
   CompressionOptions *CompressionOptions

  // EnableCompression specifies if the client should attempt to negotiate
  // per message compression (RFC 7692). Setting this value to true does not
  // guarantee that compression will be supported. Currently only "no context
  // takeover" modes are supported.
  //
  // Deprecated: Set CompressionOptions to non-nil value to enable compression
  // negotiation.
  EnableCompression bool
}

рдбрд╛рдпрд▓рд░ рдХреЛ рдорд┐рд▓рд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдКрдкрд░ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВред

@ рдЧреИрд░реАрдмрд░реНрдб рдореИрдВ рдорд╛рдирддрд╛ рд╣реВрдВ рдХрд┐ рд╕реНрддрд░ 1 рдЗрд╕ рд╕рдордп рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдХреЗ рд▓рд┐рдП рдмреЗрд╣рддрд░ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдореЗрдореЛрд░реА рдХреЛ Go1.7 рдкрд░ рдмрдврд╝рддрд╛ рд╣реИ рдФрд░ рд╕рдВрдкреАрдбрд╝рди рдЗрддрдирд╛ рдорд╣рдВрдЧрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЗрддрдиреЗ рдмрдбрд╝реЗ рдРрдкреНрд╕ рдореЗрдВ рдлреИрдирдЖрдЙрдЯ рд╕реНрддрд░ рдкрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдЬреИрд╕реЗ @joshdvir рдореЗрдВ рдмреИрдВрдбрд╡рд┐рдбреНрде рдХреА рдмрдЪрдд рдмрдЪрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рдХрдореНрдкреНрд░реЗрд╢рди рд▓реЗрд╡рд▓ рд╡рд┐рдиреНрдпрд╛рд╕ рдпреЛрдЧреНрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рд╣рдордиреЗ рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ 1 рдХреЗ рд╕рд╛рде рдПрдХ рдХрд╕реНрдЯрдо рдмрд┐рд▓реНрдб рдмрдирд╛рдпрд╛ рдФрд░ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рд╕реБрдЭрд╛рдП рдЧрдП рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдФрд░ рдЗрд╕реЗ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдбрд╛рд▓ рджрд┐рдпрд╛ред рдХрд╛рдЙрдВрдЯрд░ рдорд╛рди рд╣реИрдВ:

Node 1:
"gorilla_websocket_flate_writer_from_pool": 1453147,
"gorilla_websocket_new_flate_writer": 6702

Node 2:
"gorilla_websocket_flate_writer_from_pool": 1820919,
"gorilla_websocket_new_flate_writer": 3676,

Node 3:
"gorilla_websocket_flate_writer_from_pool": 574187,
"gorilla_websocket_new_flate_writer": 321

...

рдпрд╣ 1 рдорд┐рдирдЯ рд╕реЗ рдЕрдзрд┐рдХ рдПрдХрддреНрд░реАрдХрд░рдг рд╣реИред рддреЛ рдкреВрд▓ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡реА рджрд┐рдЦрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди ...

... рд╕рдВрдкреАрдбрд╝рди рдЕрднреА рднреА allocs рдФрд░ CPU рдкреНрд░реЛрдлрд╛рдЗрд▓ рдореЗрдВ рдЕрдЧреНрд░рдгреА рд╣реИ рдФрд░ рд╕рд┐рдВрдХ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣рд╛ рд╣реИред рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЖрд╡рдВрдЯрди-рдорд╣рдВрдЧрд╛ рдСрдкрд░реЗрд╢рди рд╣реИред

рдпрд╣рд╛рдБ рд╕реАрдкреАрдпреВ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдЕрдм рд╣реИ:

(pprof) top 30 --cum
27.28s of 52.42s total (52.04%)
Dropped 414 nodes (cum <= 0.26s)
Showing top 30 nodes out of 137 (cum >= 1.89s)
      flat  flat%   sum%        cum   cum%
         0     0%     0%     50.21s 95.78%  runtime.goexit
     0.16s  0.31%  0.31%     43.93s 83.80%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessages
     0.21s   0.4%  0.71%     42.52s 81.11%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessage
     0.19s  0.36%  1.07%     42.31s 80.71%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*wsSession).Send
     0.21s   0.4%  1.47%     41.87s 79.87%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).WriteMessage
     0.01s 0.019%  1.49%     35.43s 67.59%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*flateWriteWrapper).Close
     0.03s 0.057%  1.55%     24.69s 47.10%  compress/flate.(*Writer).Flush
         0     0%  1.55%     24.66s 47.04%  compress/flate.(*compressor).syncFlush
     0.04s 0.076%  1.62%     24.03s 45.84%  compress/flate.(*compressor).encSpeed
     0.08s  0.15%  1.77%     18.16s 34.64%  compress/flate.(*huffmanBitWriter).writeBlockDynamic
     0.12s  0.23%  2.00%     15.03s 28.67%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*messageWriter).flushFrame
     0.11s  0.21%  2.21%     14.90s 28.42%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).write
     0.91s  1.74%  3.95%     13.21s 25.20%  compress/flate.(*huffmanEncoder).generate
         0     0%  3.95%     12.72s 24.27%  net.(*conn).Write
     0.06s  0.11%  4.06%     12.72s 24.27%  net.(*netFD).Write
    11.78s 22.47% 26.54%     12.16s 23.20%  syscall.Syscall
     0.05s 0.095% 26.63%     12.09s 23.06%  syscall.Write
     0.02s 0.038% 26.67%     12.04s 22.97%  syscall.write
     0.61s  1.16% 27.83%     11.98s 22.85%  compress/flate.(*huffmanBitWriter).indexTokens
         0     0% 27.83%     10.61s 20.24%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*messageWriter).Close
     5.20s  9.92% 37.75%      6.62s 12.63%  compress/flate.(*huffmanEncoder).bitCounts
     4.77s  9.10% 46.85%      5.44s 10.38%  compress/flate.encodeBestSpeed

рд╕реВрдЪреА рд▓рд┐рдЦреЗрдВ

(pprof) list WriteMessage
Total: 52.42s
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).WriteMessage in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/conn.go
     210ms     41.87s (flat, cum) 79.87% of Total
         .          .    659:
         .          .    660:// WriteMessage is a helper method for getting a writer using NextWriter,
         .          .    661:// writing the message and closing the writer.
         .          .    662:func (c *Conn) WriteMessage(messageType int, data []byte) error {
         .          .    663:
     160ms      160ms    664:   if c.isServer && (c.newCompressionWriter == nil || !c.enableWriteCompression) {
         .          .    665:
         .          .    666:       // Fast path with no allocations and single frame.
         .          .    667:
      10ms       40ms    668:       if err := c.prepWrite(messageType); err != nil {
         .          .    669:           return err
         .          .    670:       }
         .          .    671:       mw := messageWriter{c: c, frameType: messageType, pos: maxFrameHeaderSize}
         .       80ms    672:       n := copy(c.writeBuf[mw.pos:], data)
         .          .    673:       mw.pos += n
         .          .    674:       data = data[n:]
      10ms      4.43s    675:       return mw.flushFrame(true, data)
         .          .    676:   }
         .          .    677:
         .      1.63s    678:   w, err := c.NextWriter(messageType)
         .          .    679:   if err != nil {
         .          .    680:       return err
         .          .    681:   }
      30ms      100ms    682:   if _, err = w.Write(data); err != nil {
         .          .    683:       return err
         .          .    684:   }
         .     35.43s    685:   return w.Close()

рд╕реВрдЪреА рдмрдВрдж рдХрд░реЗрдВ

         .          .    104:func (w *flateWriteWrapper) Close() error {
         .          .    105:   if w.fw == nil {
         .          .    106:       return errWriteClosed
         .          .    107:   }
         .     24.69s    108:   err1 := w.fw.Flush()
      10ms      130ms    109:   flateWriterPool.Put(w.fw)
         .          .    110:   w.fw = nil
         .          .    111:   if w.tw.p != [4]byte{0, 0, 0xff, 0xff} {
         .          .    112:       return errors.New("websocket: internal error, unexpected bytes at end of flate stream")
         .          .    113:   }
         .     10.61s    114:   err2 := w.tw.w.Close()
         .          .    115:   if err1 != nil {
         .          .    116:       return err1
         .          .    117:   }
         .          .    118:   return err2
         .          .    119:}

рд╕реВрдЪреА рдлреНрд▓рд╢

         .          .    711:// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
         .          .    712:func (w *Writer) Flush() error {
         .          .    713:   // For more about flushing:
         .          .    714:   // http://www.bolet.org/~pornin/deflate-flush.html
      30ms     24.69s    715:   return w.d.syncFlush()
         .          .    716:}
         .          .    717:
         .          .    718:// Close flushes and closes the writer.
         .          .    719:func (w *Writer) Close() error {
         .          .    720:   return w.d.close()
ROUTINE ======================== compress/flate.(*compressor).syncFlush in /Users/fz/go1.7/src/compress/flate/deflate.go
         0     24.66s (flat, cum) 47.04% of Total
         .          .    555:func (d *compressor) syncFlush() error {
         .          .    556:   if d.err != nil {
         .          .    557:       return d.err
         .          .    558:   }
         .          .    559:   d.sync = true
         .     24.03s    560:   d.step(d)
         .          .    561:   if d.err == nil {
         .      490ms    562:       d.w.writeStoredHeader(0, false)
         .      140ms    563:       d.w.flush()
         .          .    564:       d.err = d.w.err
         .          .    565:   }
         .          .    566:   d.sync = false
         .          .    567:   return d.err
         .          .    568:}

рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдм рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдЕрднреА рднреА рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИ, рд╕рдВрдкреАрдбрд╝рди рдмрд╣реБрдд рдХреБрдЫ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддрд╛ рд╣реИ:

fz<strong i="9">@centrifugo</strong>: go tool pprof --alloc_space centrifugo heap_profile_extra 
Entering interactive mode (type "help" for commands)
(pprof) top 30 --cum
518.97GB of 541.65GB total (95.81%)
Dropped 314 nodes (cum <= 2.71GB)
Showing top 30 nodes out of 35 (cum >= 3.33GB)
      flat  flat%   sum%        cum   cum%
         0     0%     0%   541.53GB   100%  runtime.goexit
         0     0%     0%   505.54GB 93.33%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessages
         0     0%     0%   504.45GB 93.13%  github.com/centrifugal/centrifugo/libcentrifugo/conns/clientconn.(*client).sendMessage
         0     0%     0%   504.45GB 93.13%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*wsSession).Send
         0     0%     0%   504.45GB 93.13%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).WriteMessage
    6.63GB  1.22%  1.22%   501.75GB 92.63%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).NextWriter
    6.56GB  1.21%  2.44%   495.11GB 91.41%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.compressNoContextTakeover
         0     0%  2.44%   491.89GB 90.81%  sync.(*Pool).Get
         0     0%  2.44%   491.89GB 90.81%  sync.(*Pool).getSlow
  359.74GB 66.42% 68.85%   488.55GB 90.20%  compress/flate.NewWriter
         0     0% 68.85%   488.55GB 90.20%  github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.glob..func1
  128.81GB 23.78% 92.63%   128.81GB 23.78%  compress/flate.(*compressor).init
    0.01GB 0.0019% 92.64%    28.97GB  5.35%  net/http.(*conn).serve
         0     0% 92.64%    25.18GB  4.65%  github.com/centrifugal/centrifugo/libcentrifugo/server/httpserver.(*HTTPServer).Logged.func1
         0     0% 92.64%    25.18GB  4.65%  net/http.(*ServeMux).ServeHTTP
         0     0% 92.64%    25.18GB  4.65%  net/http.HandlerFunc.ServeHTTP
         0     0% 92.64%    25.18GB  4.65%  net/http.serverHandler.ServeHTTP

рд╕реВрдЪреА NextWriter

(pprof) list NextWriter
Total: 541.65GB
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.(*Conn).NextWriter in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/conn.go
    6.63GB   501.75GB (flat, cum) 92.63% of Total
         .          .    444:   }
         .          .    445:
         .          .    446:   mw := &messageWriter{
         .          .    447:       c:         c,
         .          .    448:       frameType: messageType,
    6.63GB     6.63GB    449:       pos:       maxFrameHeaderSize,
         .          .    450:   }
         .          .    451:   c.writer = mw
         .          .    452:   if c.newCompressionWriter != nil && c.enableWriteCompression && isData(messageType) {
         .   495.11GB    453:       w := c.newCompressionWriter(c.writer)
         .          .    454:       mw.compress = true
         .          .    455:       c.writer = w
         .          .    456:   }
         .          .    457:   return c.writer, nil
         .          .    458:}

рд╕реВрдЪреА compressNoContextTakeover

(pprof) list compressNoContextTakeover
Total: 541.65GB
ROUTINE ======================== github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket.compressNoContextTakeover in /Users/fz/go/src/github.com/centrifugal/centrifugo/vendor/github.com/gorilla/websocket/compression.go
    6.56GB   495.11GB (flat, cum) 91.41% of Total
         .          .     44:   fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil)
         .          .     45:   return &flateReadWrapper{fr}
         .          .     46:}
         .          .     47:
         .          .     48:func compressNoContextTakeover(w io.WriteCloser) io.WriteCloser {
    4.41GB     4.41GB     49:   tw := &truncWriter{w: w}
         .   488.55GB     50:   fw, _ := flateWriterPool.Get().(*flate.Writer)
         .          .     51:   plugin.Metrics.Counters.Inc("gorilla_websocket_flate_writer_from_pool")
         .          .     52:   fw.Reset(tw)
    2.15GB     2.15GB     53:   return &flateWriteWrapper{fw: fw, tw: tw}
         .          .     54:}

--inuse_space рд╕рдорд╛рди рдЪрд┐рддреНрд░ рдХреЗрд╡рд▓ рд╕рдорд╛рди рдорд╛рддреНрд░рд╛ рдХреЗ рджреЛ рдХреНрд░рдо рдХреЛ рдХрдо рдХрд░рдХреЗ рджрд┐рдЦрд╛рддрд╛ рд╣реИ (2.69GB flateWriterPool.Get () рдХреЗ рд▓рд┐рдПред (* flate.Writer) рд▓рд╛рдЗрди рдЬреЛ рдиреЗрддрд╛ рд╣реИ)ред

рдпрд╣ рдХрд╣рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдХрд┐ рд╣рдо рдЗрддрдиреЗ рдмрдбрд╝реЗ рдХрдВрдкреНрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ...

@garyburd рдЖрдкрдХреЛ CompressionOptions рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реИ - рдореИрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рд╢рд╛рдпрдж DefaultFlateCompressionLevel рдЬреИрд╕рд╛ рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдирд┐рд░реНрдпрд╛рддрд┐рдд рдЪрд░ рдЬрд┐рд╕реЗ рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреНрд░рд╛рд░рдВрдн рдпрд╛ рд╕реЗрдЯреНрдЯрд░ рд╡рд┐рдзрд┐ рдкрд░ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рд╣рдореЗрдВ рдкреНрд░рддрд┐-рдХрдиреЗрдХреНрд╢рди рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ - рдФрд░ рд╣рдо рдЕрдВрддрддрдГ рд╡рд╣реА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЖрдкрдиреЗ рд╕реБрдЭрд╛рдпрд╛ рдерд╛ рдпрджрд┐ рдмрд╛рдж рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдФрд░ рдЕрдм рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд┐рд╕реА рднреА рддрд░рд╣ рдХреЗ рдЕрдкрдЪрдпрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреАред

@FZambia рдкреВрд▓ рдкреНрд░рднрд╛рд╡рд╢реАрд▓рддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдФрд░ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

рдореИрдВ рдЕрдм рдПрдХ рдРрд╕рд╛ рдПрдкреАрдЖрдИ рдирд╣реАрдВ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рдЬреЛ рдмрд╛рдж рдореЗрдВ рджреВрд╕рд░реЗ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдмрджрд▓ рд╕рдХреЗред

рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реЛрдЪрддрд╛ рд╣реВрдВ, рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ:

// SetCompressionLevel sets the flate compression level for the next message.
// Valid levels range from -2 to 9.  Level -2 will use Huffman compression only. 
// Level -1 uses the default compression  level.  Level 0 does not attempt any
// compression.  Levels 1 through 9 range from best speed to best compression. 
func (c *Conn) SetCompressionLevel(n int) error {
}

рдпрд╣ рдЕрдиреНрдп рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓рд╛ рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдлреНрд▓реИрдЯрд╡реЗрдЯрд░рдкреВрд▓ [12] рдХреЗ рд╕рд╛рде flateWriterPool рдХреЛ рдмрджрд▓ рджреЗрдЧрд╛ред FlateWriterWrapper рдХреЛ рд╕реНрддрд░ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рддрд╛рдХрд┐ рд▓реЗрдЦрдХ рдХреЛ рд╕рд╣реА рдкреВрд▓ рдореЗрдВ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ рдХреЛ рдмрджрд▓рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рддрд░реАрдХрд╛ рдЕрднреА рднреА рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ:

var defaultCompressionLevel int = 1

// SetDefaultCompressionLevel sets the flate compression level which will be used by 
// default to compress messages when compression negotiated. This function must be 
// called once before application starts.
//
// Valid levels range from -2 to 9.  Level -2 will use Huffman compression only. 
// Level -1 uses the default compression  level.  Level 0 does not attempt any
// compression.  Levels 1 through 9 range from best speed to best compression. 
func (c *Conn) SetDefaultCompressionLevel(n int) error {
    defaultCompressionLevel = n
}

рдЬреНрдпрд╛рджрд╛рддрд░ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХрд╕реНрдЯрдо рдХрдВрдкреНрд░реЗрд╢рди рдХреА рдЬрд░реВрд░рдд рд╡рд╛рд▓реЗ рдпреВрдЬрд░реНрд╕ рдХреЛ рдЗрд╕ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реИрд▓реНрдпреВ рдХреЛ рдПрдХ рдмрд╛рд░ рд╕реЗрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

рдлрд┐рд░ рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рдкреНрд░рддрд┐ рдХрдиреЗрдХреНрд╢рди / рд╕рдВрджреЗрд╢ рдореЗрдВ рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо SetCompressionLevel рдФрд░ рдПрдХ [12] flateWrPPP рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:

// SetCompressionLevel sets the flate compression level for the next message.
// Valid levels range from -2 to 9.  Level -2 will use Huffman compression only. 
// Level -1 uses the default compression  level.  Level 0 does not attempt any
// compression.  Levels 1 through 9 range from best speed to best compression.
// If not set default compression level will be used.
func (c *Conn) SetCompressionLevel(n int) error {
}

рдпрджрд┐ рдЗрд╕реЗ рдирд╣реАрдВ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрдкреАрдбрд╝рди рдиреЗ defaultCompressionLevel рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рддреЛ рдмрд╛рддрдЪреАрдд рд╣реЛрдЧреАред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд▓рд╛рдЧреВ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рдмрд╛рд░ рдЬреЛ рдХреИрд╡рд┐рдПрдЯ рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ SetDefaultCompressionLevel рдПрдХ рдмрд╛рд░ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рдЕрдкрд╛рд░рджрд░реНрд╢реА рд▓рдЧрддрд╛ рд╣реИред

рдмрд╕ рдкреНрд░рддреНрдпреЗрдХ flate.Writer рдЙрджрд╛рд╣рд░рдг рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рджреЗрдЦрд╛:

package main

import "unsafe"
import "compress/flate"

func main() {
    var w flate.Writer
    println(unsafe.Sizeof(w))
}

600Kb! рдпрд╣ рдЖрдХрд╛рд░ рдореЗрд░реЗ рд▓рд┐рдП рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣реИ - рдореИрдВрдиреЗ рдпрд╣ рднреА рдирд╣реАрдВ рдорд╛рдирд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЗрддрдиреА рдмрдбрд╝реА рдмрд╛рдд рд╣реИ :)

рд╣рд╛рдБ - рд░рд╛рдЬреНрдп рдХреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдлрд╝рдореИрди рдЯреЗрдмрд▓ рдФрд░ рдмрдлрд░ рдЖрдЙрдЯрдкреБрдЯ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рд╕реНрддрд░ -2 (рд╣рдлрд╝рдореИрдирдСрд▓реА), 0 (рдХреЛрдИ рд╕рдВрдкреАрдбрд╝рди рдирд╣реАрдВ) рдФрд░ 1 (рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рдЧрддрд┐) рдХреЛ рдЫреЛрдбрд╝рдХрд░, рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЕрдкрдиреА рдЦреБрдж рдХреА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рдореИрдВ рдХрдИ рдмрдлрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрдирдХреЛрдбрд┐рдВрдЧ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ, рдЬрд┐рдиреНрд╣реЗрдВ https://github.com/klauspost/compress/pull/70 (рдпрд╣ рдЕрднреА рднреА рд╕рдорд╕реНрдпрд╛ рд╣реИ, рдЬреИрд╕рд╛ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ) рджреЗрдЦреЗрдВ рджреБрд░реНрдШрдЯрдирд╛ рд╕реЗ рдореИрдВ рдореБрджреНрджреЗ рдореЗрдВ рд▓реЙрдЧ рдЗрди)

@FZambia рдореИрдВ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП рдкреИрдХреЗрдЬ рд╕реНрддрд░ рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ред рд╕реЗрдЯрд┐рдВрдЧ рдХреЛ рдбрд╛рдпрд▓рд░ рдФрд░ рдЙрдкреНрд░рдЧрдбрд░ рдореЗрдВ рдЕрдиреНрдп рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдпрд╛ рдпрд╣ рдХрдиреЗрдХреНрд╢рди рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдЗрд╕реЗ рд╕рдВрджреЗрд╢ рд╕реЗ рд╕рдВрджреЗрд╢ рдореЗрдВ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХреЗред

B0dc45572b148296ddf01989da00a2923d213a56 рджреЗрдЦреЗрдВред

@ рдЧреИрд░реАрдмрд░реНрдб рдиреЗ рдЗрд╕ рд╕рдордп рд╣рдорд╛рд░реА рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХрд╛ рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж рджрд┐рдпрд╛ред рдЗрди рд╕рднреА рдкреНрд░реЛрдлрд╛рдЗрд▓реЛрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП рдХреНрдпрд╛ рдЖрдк рд╕рдВрдкреАрдбрд╝рди рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдФрд░ рдЖрд╡рдВрдЯрди рдХреЛ рдХрдо рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рджреЗрдЦрддреЗ рд╣реИрдВ?

рдпрджрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрдИ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдПрдХ рд╣реА рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИ, рддреЛ # 182 рдЕрдЧрд▓реА рдХреЛрд╢рд┐рд╢ рд╣реИред

@garyburd # 182 рдореЗрд░реЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЬрд╛рджреВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдореЗрд░рд╛ рдкреНрд░рд╢рдВрд╕рдХ 50K-90K рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдХреЗ рдмреАрдЪ рд╣реИ рдЬрд╣рд╛рдВ рд╕рднреА рд╕рдВрджреЗрд╢ рд╕рдорд╛рди рд╣реИрдВред

рдЖрдкрдХреЗ рд╕рд╣рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

рдХреНрдпрд╛ рдпрд╣ рд╕рдорд╕реНрдпрд╛ b0dc45572b148296ddf01989da00a2923d213a56 рдФрд░ 804cb600d06b10672f2fbc0a336a7bb5050aa428e рджреНрд╡рд╛рд░рд╛ рддрдп рдХреА рдЧрдИ рд╣реИ?

рдкрд░рд┐рд╡рд░реНрддрди рд╕реЗ рдкрд╣рд▓реЗ @ рдЧреИрд░реАрдмрд░реНрдб рдвреЗрд░:
screen shot 2017-03-06 at 10 09 57
рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдмрд╛рдж (рд╕рдВрдкреАрдбрд╝рди рд╕реНрддрд░ 1 рдФрд░ PreparedMessage рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ):
screen shot 2017-03-06 at 10 10 35

рд╕реАрдкреАрдпреВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рддрд╕реНрд╡реАрд░ред рдЗрд╕рд▓рд┐рдП рд╣рдо рдкрд╣рд▓реЗ рд╕реНрдерд╛рди рдкрд░ рдвреЗрд░ рдФрд░ рд╕реАрдкреАрдпреВ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдкреАрдбрд╝рди рдирд╣реАрдВ рджреЗрдЦрддреЗ рд╣реИрдВред

рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╕реНрдореГрддрд┐ рдЙрдкрдпреЛрдЧ рдХрдо рд╣реЛ рдЧрдпрд╛ рд╣реИ рдпрд╣ рд╕рдВрдкреАрдбрд╝рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдЕрднреА рднреА рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИ - рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ, рд╣рдо рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗ

@garyburd рдиреЗ рдХреЗрд╡рд▓ inuse_space рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХреА рдШреЛрд╖рдгрд╛ рдХреА @joshdvir рдиреЗ рдореБрдЭреЗ рджрд┐рдпрд╛ред

рдиреЗрддрд╛ gorilla/websocket.newConnBRW (36%), http.newBufioWriterSize (17%), http.newBufioReader (16%) рд╣реИрдВред рдореБрдЭреЗ рд▓рдЧрд╛ рдХрд┐ рд╣рдордиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ # 223 рдореЗрдВ рдЬреЛрдбрд╝реЗ рдЧрдП рд╕реБрдзрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрд┐рди рдкреНрд░реЛрдлрд╛рдЗрд▓ рдкрд░ рдореИрдВрдиреЗ рдЧреМрд░ рдХрд┐рдпрд╛ рд╣реИ, рдЙрдиреНрд╣реЛрдВрдиреЗ рджреЗрдЦрд╛ рдХрд┐ hijack рд╕реЗ рдмрдлрд╝рд░реНрд╕ рдкрдврд╝рдирд╛ рдФрд░ рд▓рд┐рдЦрдирд╛ рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдкреБрди: рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рддрдм рдореБрдЭреЗ рд╕реЗрдВрдЯреНрд░реАрдлреБрдЧреЛ рдХреЛрдб рдореЗрдВ рдПрдХ рдмрдЧ рдорд┐рд▓рд╛ - ReadBufferSize рдФрд░ WriteBufferSize рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдП рдЧрдП рдЙрди рдЖрдХрд╛рд░реЛрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ SockJS-go рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди (4096) рдереЗред рддрдп рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдЧрд╛ рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рд╡рд╛рдкрд╕ рдЖрдПрдЧрд╛ред

рдкреНрд░реЛрдлрд╛рдЗрд▓ рдореЗрдВ рдХреБрдЫ рдЕрдиреНрдп рдЪреАрдЬреЗрдВ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рд░реБрдЪрд┐ рджреЗ рд╕рдХрддреА рд╣реИрдВ - рдореИрдВ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд╕рд╛рде svg рдЧреНрд░рд╛рдл рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЛ рдлрд┐рдХреНрд╕ рдХреЗ рд╕рд╛рде рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реВрдВрдЧрд╛ред

рдирд╡реАрдирддрдо рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рд╡реЗрдмрд╕реЛрдХреЗрдЯ рдХреЗ рд╕рд╛рде рд╕реЗрдВрдЯреНрд░реАрдлреБрдЧреЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреБрдЫ рдЧреНрд░рд╛рдлрд╝ рдпрд╣рд╛рдВ рджрд┐рдП рдЧрдП рд╣реИрдВред рдпрд╣ @joshdvir рджреНрд╡рд╛рд░рд╛

CPU:

screen shot 2017-03-31 at 23 54 19

рдпрд╣рд╛рдБ рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕реАрдкреАрдпреВ syscalls рдкрд░ рдЦрд░реНрдЪ рд╣реЛрддреЗ рд╣реИрдВ - рдкрдврд╝рддреЗ рд╣реИрдВ, рд▓рд┐рдЦрддреЗ рд╣реИрдВ - рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рд╣рдо рдпрд╣рд╛рдБ рдмрд╣реБрдд рдХреБрдЫ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕реЙрдХреЗрдЯ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдлреИрдирдЖрдЙрдЯ рд╕рдВрджреЗрд╢ рднреЗрдЬрддреЗ рд╣реИрдВред рддреЛ рдпрд╣ рд╕рд╛рдорд╛рдиреНрдп рд▓рдЧ рд░рд╣рд╛ рд╣реИред

рд╕реНрдерд╛рди рдЖрд╡рдВрдЯрд┐рдд рдХрд░реЗрдВ:

screen shot 2017-03-31 at 23 52 49

рдпрд╣рд╛рдВ рд╣рдо compress/flate.(*decompressor).Reset рдХрд╛ рдПрдХ рдмрдбрд╝рд╛ рдкреНрд░рднрд╛рд╡ рджреЗрдЦрддреЗ рд╣реИрдВ - рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рд╕реБрдзрд╛рд░реЗрдВ, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдХреЛрдИ рд░рд╛рд╕реНрддрд╛ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИред

рдЕрдВрддрд░рд┐рдХреНрд╖ рдореЗрдВ рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВ:

screen shot 2017-04-01 at 00 00 31

@ рдЧреИрд░реАрдмрд░реНрдб рдЖрдкрдХреЛ рдЖрдЧреЗ рдЪреАрдЬреЛрдВ рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ? рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рд░рд╣ рд╕рдХрддреЗ рд╣реИрдВ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИред

рдкреАрдПрд╕ рдореИрдВ рд╕реНрдерд╛рдиреАрдп рдорд╢реАрди рдкрд░ рд╕рдВрдкреАрдбрд╝рди рд╕рдХреНрд╖рдо / рдЕрдХреНрд╖рдо рдФрд░ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХреА рддреБрд▓рдирд╛ рдХреЗ рд╕рд╛рде рдХрдИ ws рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВред

рдореБрдЭреЗ рдХреБрдЫ рдЯреНрд╡рд┐рдХреНрд╕ рдорд┐рд▓реЗ рдЬреЛ рдХрд┐ рдбрд┐рдХреЛрдбрд░ рдХреЛ рдЖрд╡рдВрдЯрди рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рдерд╛, рдФрд░ 4KB рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЖрд╡рдВрдЯрди рдХреЛ рд╕реНрдердЧрд┐рдд рдХрд░рдирд╛ рдЬрдм рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реЛред

https://github.com/klauspost/compress/pull/76

рдореБрдЭреЗ рд╡реЗрдмрд╕реИрдЯ рдкреИрдХреЗрдЬ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рджрд┐рдЦ рд░рд╣рд╛ рд╣реИред

рдмрд╕ рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдкрд░ рдХреЛрд╢рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИ - рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореЗрдореЛрд░реА рдХреА рдЦрдкрдд рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЬрдЧрд╣реЛрдВ рд╕реЗ рдХрдо рдпрд╛ рдЬреНрдпрд╛рджрд╛ рд╕рдорд╛рди рдЕрдиреБрдкрд╛рдд рдореЗрдВ рд╣реЛрддреА рд╣реИ рдЗрд╕рд▓рд┐рдП рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдбрд╝рдЪрди рдХрд╛ рдирд┐рджрд╛рди рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдпрд╣рд╛рдБ рдЙрд╕ рд╕рдордп рдХреЗ рд▓рд┐рдП рдХрд░ рд░рд╣реЗ рд╣реИрдВред

@рдХреНрд▓рд╛рд╕рдкреЛрд╕реНрдЯ рдореИрдВрдиреЗ рд╕реНрдерд╛рдиреАрдп рд╕реЗрдЯрдЕрдк рдкрд░ рднреА рдЖрдкрдХреЗ рдХреЙрдореНрдкреНрд░реЗрд╕реЗрдб рд▓рд┐рдм рдХреА рдХреЛрд╢рд┐рд╢ рдХреА (1000 рдХреНрд▓рд╛рдЗрдВрдЯреНрд╕ рдХреЛ рдиреЛрдб рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░реЗрдВ) - рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдореЗрдореЛрд░реА рдХреА рдЦрдкрдд рдмрд┐рдирд╛ рдХрдВрдкреНрд░реЗрд╢рди рдХреЗ 50 рдЧреНрд░рд╛рдо, рдПрд╕рдЯреАрдбреА рдХреА рдХрдореНрдкреНрд░реЗрд╢рди рдХрдореНрдкреНрд░реЗрд╢рди рдХреЗ рд╕рд╛рде 90mb, рдкреИрдЪ рдХреЗ рдмрд┐рдирд╛ рдЖрдкрдХреА рд▓рд┐рдмрд╛рд╕ рдХреЗ рд╕рд╛рде 90mb рдФрд░ рдкреИрдЪ https рдХреЗ рд╕рд╛рде рдЖрдкрдХреЗ 85mb рдХреА рд╣реИред

Go1.8.1 рд╕реЗ рдЧреЛ 1.7.5 рдореЗрдВ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рд╕реЗ рдореЗрд░реЗ рдХреГрддреНрд░рд┐рдо рд╕реНрдерд╛рдиреАрдп рд╕реЗрдЯрдЕрдк рдкрд░ рд▓рдЧрднрдЧ 15% (90mb -> 75mb) рд╕реЗ рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реБрдЖред рд▓реЗрдХрд┐рди рдореИрдВ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдХрд╣ рд╕рдХрддрд╛ рдХрд┐ рдпрд╣ рд▓рд╛рдн рдХрд╣рд╛рдВ рд╕реЗ рдЖрдпрд╛ред

рд╕рдореНрдкреАрдбрди рд╕рдХреНрд╖рдо рдореЗрдореЛрд░реА рдХреЗ рд╕рд╛рде рдЙрддреНрдкрд╛рджрди рдЙрджрд╛рд╣рд░рдг рдкрд░ рднреА рдЧреЛ 1.8 рдХреЗ рд╕рд╛рде рд╕рдорд╛рди 15-20% рдкрд░ рдЧрд┐рд░ рдЧрдпрд╛

@joshdvir @FZambia (рдФрд░ рдЕрдиреНрдп), рдХреНрдпрд╛ рд╣рдореЗрдВ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЧреЛ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рд╕реБрдзрд╛рд░ рдХреЗ рд╕рд╛рде рд╕рдВрдмреЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдЕрднреА рднреА рдХреБрдЫ рдиреАрдЪреЗ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ?

@theckman рд╣рд╛рдп, рдореЗрд░реЗ рдкрд╛рд╕ рдХреЛрдИ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдо рдЖрдЧреЗ рдХреИрд╕реЗ рд╕рдВрдкреАрдбрд╝рди рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рд▓ рд╣реЛ рдЧрдИ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрдкреАрдбрд╝рди рдЕрднреА рднреА рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ - рдЗрд╕реЗ рдмреЗрдЭрд┐рдЭрдХ рдХрд░реЗрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХреНрд╖рд┐рддрд┐рдЬ рдкрд░ рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИред рд╕реНрдерд┐рддрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ PreparedMessage рдПрдХ рдЬреАрд╡рди рд░рдХреНрд╖рдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдЗрд╕рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдмрд╣реБрдд рдкрд╕рдВрдж рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдмрд╣реБрдд рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИ рдФрд░ рдХрдиреЗрдХреНрд╢рди рдореЗрдВ рдмрд╛рдЗрдЯреНрд╕ рд▓рд┐рдЦрдиреЗ рдХреЗ рд╢рдмреНрджрд╛рд░реНрде рдХреЛ рддреЛрдбрд╝рддрд╛ рд╣реИред

рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЕрдЧрд░ рдЖрдкрдиреЗ рдПрдХ рдХрд╛рдлреА рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди рдмреЗрдВрдЪрдорд╛рд░реНрдХ рд▓рд┐рдЦрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рдХреЗрд╡рд▓ рд╕реНрдЯреИрдбрд▓рд┐рдм рдФрд░ рдбрд┐рдлреНрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рдЬреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреЗ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрд┐ рдореИрдВ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдпрджрд┐ рдПрдХ рд▓реАрдирд░ рдПрдирдХреЛрдбрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред

рдкреАрдЖрд░ рдЦреБрдж рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдЕрдЪреНрдЫрд╛ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рд╣реЛрдирд╛ рдПрдХ рд╢реБрд░реБрдЖрддреА рдмрд┐рдВрджреБ рд╣реЛрдЧрд╛ред

рд╣рдо рдПрдХ []byte -> []byte API рднреА рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рдкреВрд░реНрдг рдлреНрд░реЗрдо рдХреА рдЖрдкреВрд░реНрддрд┐ рдХреА рдЬрд╛рддреА рд╣реИ рдЬреЛ рдЖрдВрддрд░рд┐рдХ рдмрдлрд░ (рдФрд░ рдЗрд╕реЗ рдХреЙрдкреА рдХрд░рдиреЗ рдХреЗ рджрдВрдб) рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрдЧрд╛ред

рдЗрди рдкреНрд░рджрд░реНрд╢рди рдореБрджреНрджреЛрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рд╕рдВрдкреАрдбрд╝рди рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИ?

рд╣рдо рдПрдХ [] рдмрд╛рдЗрдЯ -> [] рдмрд╛рдЗрдЯ рдПрдкреАрдЖрдИ рднреА рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рдкреВрд░реНрдг рдлреНрд░реЗрдо рдХреА рдЖрдкреВрд░реНрддрд┐ рдХреА рдЬрд╛рддреА рд╣реИ рдЬреЛ рдПрдХ рдЖрдВрддрд░рд┐рдХ рдмрдлрд░ (рдФрд░ рдЗрд╕реЗ рдХреЙрдкреА рдХрд░рдиреЗ рдХреЗ рджрдВрдб) рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрдЧрд╛ред

рдпрд╣ рдПрдкреАрдЖрдИ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛? рдХреНрдпрд╛ рд╣рдо рд╕реАрдзреЗ net.Conn рдкрд░ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВрдЧреЗ?

рд╕рдВрдкреАрдбрд╝рди рдХреЗ рдмрд┐рдирд╛ рд╕рд░реНрд╡рд░ рдкрд░, WriteMessage API рдЬреНрдпрд╛рджрд╛рддрд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдиреЗрдЯрд╡рд░реНрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рджрд┐рдП рдЧрдП [] рдмрд╛рдЗрдЯ рд╕реЗ рд╕реАрдзреЗ рдбреЗрдЯрд╛ рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рддрд╛ рд╣реИред рддреИрдпрд╛рд░ рд╕рдВрджреЗрд╢ рдПрдкреАрдЖрдИ рднреА рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдиреЗрдЯрд╡рд░реНрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╕реАрдзреЗ [] рдмрд╛рдЗрдЯ рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рддрд╛ рд╣реИред

рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдореБрджреНрджрд╛ рд╕рдВрдкреАрдбрд╝рд┐рдд рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдг рд╣реИред Https://golang.org/issue/3155 рджреЗрдЦреЗрдВ

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдкреНрд░рддреНрдпреЗрдХ рдлреНрд▓реИрдЯ рд▓реЗрдЦрдХ рдмрд╣реБрдд рд╕рд╛рд░реА рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рднрд▓реЗ рд╣реА рд╡реЗ рдкреВрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдпрд╣ рдЕрдВрдд рдореЗрдВ рд╕рдВрдкреАрдбрд╝рди рдХреЗ рд╕рд╛рде рдмрдбрд╝реЗ рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рд╕реНрдкрд╛рдЗрдХ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред

рдРрд╕рд╛ рдирд╣реАрдВ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдмрдВрдж рд╣реЛрдиреЗ рддрдХ рдпрд╣ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЖрдЧреЗ рднреА рдХреБрдЫ рдХрд░ рд╕рдХрддреА рд╣реИред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЗрд╕ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХреЗ рдЕрдиреБрд╕рд╛рд░


func BenchmarkFlate(b *testing.B) {
    b.ReportAllocs()
    for i := 0; i < b.N; i++ {
        flate.NewWriter(nil, flate.BestSpeed)
    }
}
$ go test -bench=BenchmarkFlate -run=^$
goos: darwin
goarch: amd64
pkg: scratch
BenchmarkFlate-8       10000        131504 ns/op     1200008 B/op         15 allocs/op
PASS
ok      scratch 1.345s

flate.NewWriter 1.2 MB рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддрд╛ рд╣реИ! рдЬрдм рдЖрдк 600 рдмрд╛рдЗрдЯ рд╡реЗрдмрд╕реНрдХреЗрдЯ рд╕рдВрджреЗрд╢ рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рд╕рдВрдкреАрдбрд╝рди рдХреЗ рд▓рд┐рдП рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдмрд╣реБрдд рдореЗрдореЛрд░реА рд╣реИред

BestCompression рдпрд╛ DefaultCompress рдХреЗ рд╕рд╛рде, рдЖрд╡рдВрдЯрди 800 рдХреЗрдмреА рдЧрд┐рд░рд╛ рджреЗрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдЕрднреА рднреА рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рд╣реИред

# DefaultCompression
$ go test -bench=BenchmarkFlate -run=^$
goos: darwin
goarch: amd64
pkg: nhooyr.io/websocket
BenchmarkFlate-8       20000         93332 ns/op      806784 B/op         13 allocs/op
PASS
ok      nhooyr.io/websocket 2.848s
# BestCompression
$ go test -bench=BenchmarkFlate -run=^$
goos: darwin
goarch: amd64
pkg: nhooyr.io/websocket
BenchmarkFlate-8       20000         95197 ns/op      806784 B/op         13 allocs/op
PASS
ok      nhooyr.io/websocket 2.879s

рдореИрдВрдиреЗ рдЧреЛрд▓рдВрдЧ рджрд╛рдпрд░ рдХрд┐рдпрд╛ рд╣реИ / # 32371 рдЬрд╛рдУ

Https://github.com/klauspost/compress/pull/176 рдкрд░ рдПрдХ рдирдЬрд░ рдбрд╛рд▓реЗрдВ

@klauspost рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рд▓рд┐рдЦреЗрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдореЗрдореЛрд░реА рдУрд╡рд░рд╣реЗрдб рд╢рд╛рдорд┐рд▓ рд╣реЛрдЧреА?

рдпрд╣ рдХреБрдЫ рд╕реМ рдХрд┐рд▓реЛрдмрд╛рдЗрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рд▓реЗрдХрд┐рди рдПрдХ рдмрд╛рд░ рдЬрдм рдпрд╣ рд╕рдВрдХреБрдЪрд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдЕрдиреНрдп рд╡рд┐рдХрд▓реНрдкреЛрдВ рд╕реЗ рдкрд╣рд▓реЗ рдХреЗ рд╡рд┐рдкрд░реАрдд рд╕реНрдореГрддрд┐ рдХреЛ рдореБрдХреНрдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╡реЗрдм рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП, рдЬреЛ рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдПред рдорддрд▓рдм рдирд┐рд╖реНрдХреНрд░рд┐рдп рд╕реЙрдХреЗрдЯ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд▓рд╛рдЗрд╡ рдЖрд╡рдВрдЯрди рдирд╣реАрдВред рдмрд╕ рдпрдХреАрди рд╣реИ рдХрд┐ рд╕рднреА рдПрдХ рд╣реА рд▓реЗрдЦрди рдореЗрдВ рд▓рд┐рдЦрд╛ рд╣реИред

@klauspost рдзрдиреНрдпрд╡рд╛рдж, рдореИрдВ рд╕рдордп рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдЬрд┐рд╕реНрдЯ рд╣реИ рдЬреЛ рдЧреЛрд░рд┐рд▓реНрд▓рд╛ рд╡реЗрдмрд╕реНрдХреЗрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рд╛рде рдХрд╕реНрдЯрдо рдлреНрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ - рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдиреЗ рдФрд░ рдЕрдкрдиреА рд╕реНрдЯреЗрдЯрд▓реЗрд╕ рдХрдореНрдкреНрд░реЗрд╢рди рдмреНрд░рд╛рдВрдЪ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

https://github.com/klauspost/compress/pull/185 рдПрдХ рдЖрдВрддрд░рд┐рдХ sync.Pool рд╣реЛрдиреЗ рдкрд░ рд▓рд┐рдЦрдХрд░ рдХреБрдЫ рд╕реМ рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рдвреЗрд░ рдЖрд╡рдВрдЯрди рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИред

рд╕реНрдЯреЗрдЯрд▓реЗрд╕ рдХрдореНрдкреНрд░реЗрд╢рди рдХреЗ рд╕рд╛рде @klauspost рдХреА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рдиреЗ рд╢рд╛рдирджрд╛рд░ рдкрд░рд┐рдгрд╛рдо рджрд┐рдЦрд╛рдП рд╣реИрдВред

Https://github.com/klauspost/compress/pull/216#issuecomment -586660128 рджреЗрдЦреЗрдВ

рд▓рдЧрднрдЧ 512 KB рдкреНрд░рддрд┐ рд╕рдВрджреЗрд╢ рд╕рд░рд▓ 512 рдмрд╛рдЗрдЯ рд╕рдВрджреЗрд╢ []byte(strings.Repeat("1234", 128)) рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдпрд╣ рдЕрдм рдореЗрд░реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдкрд░ рдорд╛рд╕реНрдЯрд░ рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реИред

рд╕реНрдкрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╕рдВрджрд░реНрдн рдЯреЗрдХрдУрд╡рд░ рдореЛрдб рдореЗрдВ рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рдХреЗ рд╕рд╛рде рд╣реИ, рдпрд╣ 50 рдмреА рд╣реИ рдПрдХ рд╕рдВрджреЗрд╢ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЕрдЧрд░ рдХреЛрдИ рд╢рдмреНрджрдХреЛрд╢ рдирд╣реАрдВ рд╣реИред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

markusthoemmes picture markusthoemmes  ┬╖  7рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Mjavala picture Mjavala  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

fbens picture fbens  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

weiyixuan picture weiyixuan  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

lexansoft picture lexansoft  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ