gnet icon indicating copy to clipboard operation
gnet copied to clipboard

lockFreeQueue的gc问题

Open zhu121 opened this issue 2 years ago • 2 comments

lock_free_queue.go的Enqueue()函数内的n := &node{value: task}会调用到runtime.newobject和runtime.mallocgc, Enqueue()频繁调用时,是否会有gc问题,是否考虑用类似sync.Pool的形式来管理node

zhu121 avatar Dec 02 '21 08:12 zhu121

你可以测一下,然后把数据贴出来看看,看看是不是的确会有很大影响。

panjf2000 avatar Dec 05 '21 11:12 panjf2000

1.新增的测试代码/cmd/main.go

type testCodec struct {
}

func (cc *testCodec) Encode(c gnet.Conn, buf []byte) (out []byte, err error) {
	return buf, nil
}

func (cc *testCodec) Decode(c gnet.Conn) ([]byte, error) {
	var buf innerBuffer
	buf = c.Read()
	msg, _ := buf.readN(4)
	if msg == nil {
		return nil, nil
	}
	c.ShiftN(4)
	return msg, nil
}

type testServer struct {
	*gnet.EventServer
	svr        gnet.Server
	protoAddr  string
	workerPool *goroutine.Pool
}

func (s *testServer) React(packet []byte, c gnet.Conn) (out []byte, action gnet.Action) {
	data := append([]byte{}, packet...)
	_ = s.workerPool.Submit(func() {
		_ = c.AsyncWrite(data)
	})
	return nil, gnet.None
}

func main() {
	f, _ := os.OpenFile("gate-cpu.pprof", os.O_CREATE|os.O_RDWR, 0644)
	_ = pprof.StartCPUProfile(f)
	defer func() {
		pprof.StopCPUProfile()
		f.Close()
	}()
	ts := &testServer{
		protoAddr:  "tcp4://0.0.0.0:9999",
		workerPool: goroutine.Default(),
	}
	go func() {
		time.Sleep(70 * time.Second)
		_ = gnet.Stop(context.TODO(), ts.protoAddr)
	}()
	err := gnet.Serve(ts,
		ts.protoAddr,
		gnet.WithLockOSThread(true),
		gnet.WithNumEventLoop(3),
		gnet.WithReuseAddr(true),
		gnet.WithTCPNoDelay(gnet.TCPNoDelay),
		gnet.WithCodec(&testCodec{}),
		gnet.WithLoadBalancing(gnet.LeastConnections))
	fmt.Println("serve", err)
}

2.go tool pprof数据: Showing nodes accounting for 137.59s, 86.26% of 159.51s total Dropped 228 nodes (cum <= 0.80s) Showing top 10 nodes out of 65 flat flat% sum% cum cum% 83.39s 52.28% 52.28% 83.39s 52.28% runtime.futex 35.05s 21.97% 74.25% 36.85s 23.10% syscall.Syscall 13.13s 8.23% 82.48% 13.58s 8.51% syscall.Syscall6 1.17s 0.73% 83.22% 65.22s 40.89% github.com/panjf2000/gnet/internal/netpoll.(*Poller).Polling 0.92s 0.58% 83.79% 3.53s 2.21% runtime.mallocgc

3.runtime.mallocgc相关的调用 gnet(*Conn).AsyncWrite -> runtime.mallocgc gnet(*Conn).AsyncWrite -> runtime.newobject -> runtime.mallocgc gnet(*Conn).AsyncWrite -> netpoll(*Poller).Tigger -> runtime.newobject -> runtime.mallocgc main(*testServer).React -> runtime.growslice -> runtime.mallocgc

zhu121 avatar Dec 06 '21 09:12 zhu121