Closed
Description
I wrote some tests, here is my code:
package main
import (
"net/http"
"io"
"fmt"
"nhooyr.io/websocket"
"context"
"time"
"bytes"
"runtime"
)
func main(){
go func(){
http.ListenAndServe(`127.0.0.1:9098`,echoServer{})
}()
time.Sleep(time.Millisecond*10)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
c, _, err := websocket.Dial(ctx, `http://127.0.0.1:9098`, &websocket.DialOptions{
Subprotocols: []string{"echo"},
})
defer c.Close(websocket.StatusNormalClosure,``)
ctx = context.Background()
inList:=[]byte{1}
buf:=make([]byte,1024)
c2:=websocket.NetConn(ctx,c,websocket.MessageBinary)
runLoopOnceFn:=func(){
_,err=c2.Write(inList)
if err!=nil{
panic(err)
}
for {
nr,err := c2.Read(buf)
if err!=nil{
panic(err)
}
if nr==0{
continue
}
if nr!=1 || bytes.Equal(buf[:nr],inList)==false{
panic(`b7wdgy9dyz`)
}
return
}
}
for i:=0;i<1024;i++{
runLoopOnceFn()
}
var m runtime.MemStats
runtime.ReadMemStats(&m)
startAllocSize:=m.TotalAlloc
startAllocNum:=m.Mallocs
const loopNum = 1024
for i:=0;i<loopNum;i++{
runLoopOnceFn()
}
runtime.ReadMemStats(&m)
endAllocSize:=m.TotalAlloc
endAllocNum:=m.Mallocs
fmt.Println("AllocSize",float64(endAllocSize-startAllocSize)/float64(loopNum))
fmt.Println("AllocNum",float64(endAllocNum-startAllocNum)/float64(loopNum))
}
// echoServer is the WebSocket echo server implementation.
// It ensures the client speaks the echo subprotocol and
// only allows one message every 100ms with a 10 message burst.
type echoServer struct {
// logf controls where logs are sent.
logf func(f string, v ...interface{})
}
func (s echoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
Subprotocols: []string{"echo"},
})
if err != nil {
s.logf("%v", err)
return
}
defer c.Close(websocket.StatusInternalError, "the sky is falling")
if c.Subprotocol() != "echo" {
c.Close(websocket.StatusPolicyViolation, "client must speak the echo subprotocol")
return
}
for {
err = echo(r.Context(), c)
if websocket.CloseStatus(err) == websocket.StatusNormalClosure {
return
}
if err != nil {
s.logf("failed to echo with %v: %v", r.RemoteAddr, err)
return
}
}
}
// echo reads from the WebSocket connection and then writes
// the received message back to it.
// The entire function has 10s to complete.
func echo(ctx context.Context, c *websocket.Conn) error {
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
typ, r, err := c.Reader(ctx)
if err != nil {
return err
}
w, err := c.Writer(ctx, typ)
if err != nil {
return err
}
_, err = io.Copy(w, r)
if err != nil {
return fmt.Errorf("failed to io.Copy: %w", err)
}
err = w.Close()
return err
}
- I got result:
AllocSize 33131.9296875
AllocNum 9.0244140625
- here is alloc place list in one runLoopOnceFn call (with my internal tool, may open source soon)
=========================================================
allocSize: 32.00KB allocNum: 1.0000B percentSize: 99.83%
type: uint8
/usr/local/go/src/runtime/malloc.go:1121
/usr/local/go/src/runtime/slice.go:103
/usr/local/go/src/io/io.go:424
/usr/local/go/src/io/io.go:386
main.go:119
main.go:91
/usr/local/go/src/net/http/server.go:2947
/usr/local/go/src/net/http/server.go:1991
/usr/local/go/src/net/http/server.go:3102
/usr/local/go/src/runtime/asm_amd64.s:1594
/usr/local/go/src/net/http/server.go:3102
=========================================================
allocSize: 24.000B allocNum: 1.0000B percentSize: 0.07%
type: websocket.CloseError
/usr/local/go/src/runtime/malloc.go:1121
/usr/local/go/src/runtime/malloc.go:1192
src/nhooyr.io/websocket/close.go:71
main.go:92
/usr/local/go/src/net/http/server.go:2947
/usr/local/go/src/net/http/server.go:1991
/usr/local/go/src/net/http/server.go:3102
/usr/local/go/src/runtime/asm_amd64.s:1594
/usr/local/go/src/net/http/server.go:3102
=========================================================
allocSize: 16.000B allocNum: 1.0000B percentSize: 0.05%
type: websocket.msgWriter
/usr/local/go/src/runtime/malloc.go:1121
/usr/local/go/src/runtime/malloc.go:1192
src/nhooyr.io/websocket/write.go:115
src/nhooyr.io/websocket/write.go:122
src/nhooyr.io/websocket/write.go:42
src/nhooyr.io/websocket/netconn.go:84
main.go:32
main.go:66
/usr/local/go/src/runtime/proc.go:250
/usr/local/go/src/runtime/asm_amd64.s:1594
=========================================================
allocSize: 16.000B allocNum: 1.0000B percentSize: 0.05%
type: websocket.msgWriter
/usr/local/go/src/runtime/malloc.go:1121
/usr/local/go/src/runtime/malloc.go:1192
src/nhooyr.io/websocket/write.go:115
src/nhooyr.io/websocket/write.go:28
main.go:114
main.go:91
/usr/local/go/src/net/http/server.go:2947
/usr/local/go/src/net/http/server.go:1991
/usr/local/go/src/net/http/server.go:3102
/usr/local/go/src/runtime/asm_amd64.s:1594
/usr/local/go/src/net/http/server.go:3102