Commit 8c878d57 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Remove pre-spawned goroutine pool.

The benchmarks cannot accurately identify its benefit, and it has a
tangible drawback in that it locks up the daemon if it has many
blocking calls.
parent ebb901ab
...@@ -118,17 +118,7 @@ func (me *MountState) BufferPoolStats() string { ...@@ -118,17 +118,7 @@ func (me *MountState) BufferPoolStats() string {
return me.buffers.String() return me.buffers.String()
} }
func (me *MountState) newRequest(oldReq *request) *request { func (me *MountState) newRequest() *request {
if oldReq != nil {
me.buffers.FreeBuffer(oldReq.flatData)
*oldReq = request{
status: OK,
inputBuf: oldReq.inputBuf[0:bufSize],
}
return oldReq
}
return &request{ return &request{
status: OK, status: OK,
inputBuf: me.buffers.AllocBuffer(bufSize), inputBuf: me.buffers.AllocBuffer(bufSize),
...@@ -165,24 +155,14 @@ func (me *MountState) recordStats(req *request) { ...@@ -165,24 +155,14 @@ func (me *MountState) recordStats(req *request) {
// //
// If threaded is given, each filesystem operation executes in a // If threaded is given, each filesystem operation executes in a
// separate goroutine. // separate goroutine.
func (me *MountState) Loop(threaded bool) { func (me *MountState) Loop(unused bool) {
// To limit scheduling overhead, we spawn multiple read loops.
// This means that the request once read does not need to be
// assigned to another thread, so it avoids a context switch.
if threaded {
for i := 0; i < me.opts.MaxBackground-1; i++ {
go me.loop()
}
}
me.loop() me.loop()
me.mountFile.Close() me.mountFile.Close()
} }
func (me *MountState) loop() { func (me *MountState) loop() {
var lastReq *request
for { for {
req := me.newRequest(lastReq) req := me.newRequest()
lastReq = req
err := me.readRequest(req) err := me.readRequest(req)
if err != nil { if err != nil {
errNo := OsErrorToErrno(err) errNo := OsErrorToErrno(err)
...@@ -200,10 +180,24 @@ func (me *MountState) loop() { ...@@ -200,10 +180,24 @@ func (me *MountState) loop() {
log.Printf("Failed to read from fuse conn: %v", err) log.Printf("Failed to read from fuse conn: %v", err)
break break
} }
me.handleRequest(req)
// When closely analyzing timings, the context switch
// generates some delay. While unfortunate, the
// alternative is to have a fixed goroutine pool,
// which will lock up the FS if the daemon has too
// many blocking calls.
go func(r *request) {
me.handleRequest(r)
me.discardRequest(r)
}(req)
} }
} }
func (me *MountState) discardRequest(req *request) {
me.buffers.FreeBuffer(req.flatData)
me.buffers.FreeBuffer(req.inputBuf)
}
func (me *MountState) handleRequest(req *request) { func (me *MountState) handleRequest(req *request) {
defer me.recordStats(req) defer me.recordStats(req)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment