Skip to content

Commit

Permalink
use goroutine pool to concurrent forgetinode
Browse files Browse the repository at this point in the history
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
  • Loading branch information
kungf committed Mar 17, 2020
1 parent 7d791d2 commit 7dd5564
Showing 1 changed file with 24 additions and 5 deletions.
29 changes: 24 additions & 5 deletions fuseutil/file_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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 {
Expand All @@ -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)
}
Expand Down

0 comments on commit 7dd5564

Please sign in to comment.