From 7dd556422a7a026caf304ff778d26695effcc9d0 Mon Sep 17 00:00:00 2001 From: kungf Date: Tue, 17 Mar 2020 11:30:46 +0800 Subject: [PATCH] use goroutine pool to concurrent forgetinode in #30 forgetinode was changed into inline ServerOps, this may solove memory oom, but the performance of rm op will be very slow, and it will also hang other ops, so i think add a goroutine pool to limit the max num of forgetinode goroutines, but not affect the performance --- fuseutil/file_system.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/fuseutil/file_system.go b/fuseutil/file_system.go index 5eb8bcaa..48948830 100644 --- a/fuseutil/file_system.go +++ b/fuseutil/file_system.go @@ -21,6 +21,7 @@ import ( "github.com/jacobsa/fuse" "github.com/jacobsa/fuse/fuseops" + "github.com/panjf2000/ants/v2" ) // An interface with a method for each op type in the fuseops package. This can @@ -93,6 +94,12 @@ type fileSystemServer struct { opsInFlight sync.WaitGroup } +type opCtx struct { + c *fuse.Connection + ctx context.Context + op interface{} +} + func (s *fileSystemServer) ServeOps(c *fuse.Connection) { // When we are done, we clean up by waiting for all in-flight ops then // destroying the file system. @@ -101,6 +108,17 @@ func (s *fileSystemServer) ServeOps(c *fuse.Connection) { s.fs.Destroy() }() + // forget inode ops, which may come in a + // flurry from the kernel and we should + // make a pool to limit the number of goroutines + // one goroutine 2KB, 10w goroutine max 200MB + p, _ := ants.NewPoolWithFunc(100000, func(i interface{}) { + op := i.(opCtx) + s.handleOp(op.c, op.ctx, op.op) + }) + + defer p.Release() + for { ctx, op, err := c.ReadOp() if err == io.EOF { @@ -113,11 +131,12 @@ func (s *fileSystemServer) ServeOps(c *fuse.Connection) { s.opsInFlight.Add(1) if _, ok := op.(*fuseops.ForgetInodeOp); ok { - // Special case: call in this goroutine for - // forget inode ops, which may come in a - // flurry from the kernel and are generally - // cheap for the file system to handle - s.handleOp(c, ctx, op) + op := &opCtx{ + c: c, + ctx: ctx, + op: op, + } + p.Invoke(op) } else { go s.handleOp(c, ctx, op) }