Avoid calling Logf on the hot path when logging is disabled.

The call to commonOp.Logf in sendBazilfuseResponse is extremely hot for
allocations, presumably because it needs to allocate an argument slice.
It is normally not needed at all, so why pay for it?
geesefs-0-30-9
Aaron Jacobs 2015-07-22 21:45:49 +10:00
parent 4b1e4b55f9
commit f004d3ff4a
4 changed files with 40 additions and 27 deletions

View File

@ -50,6 +50,8 @@ type Connection struct {
// Responsibility for closing the wrapped connection is transferred to the
// result. You must call c.close() eventually.
//
// The loggers may be nil.
func newConnection(
parentCtx context.Context,
debugLogger *log.Logger,
@ -73,6 +75,10 @@ func (c *Connection) debugLog(
calldepth int,
format string,
v ...interface{}) {
if c.debugLogger == nil {
return
}
// Get file:line info.
var file string
var line int
@ -239,8 +245,11 @@ func (c *Connection) ReadOp() (op fuseops.Op, err error) {
// Set up op dependencies.
opCtx := c.beginOp(bfReq)
debugLogForOp := func(calldepth int, format string, v ...interface{}) {
c.debugLog(opID, calldepth+1, format, v...)
var debugLogForOp func(int, string, ...interface{})
if c.debugLogger != nil {
debugLogForOp = func(calldepth int, format string, v ...interface{}) {
c.debugLog(opID, calldepth+1, format, v...)
}
}
finished := func(err error) { c.finishOp(bfReq) }

View File

@ -49,9 +49,13 @@ type commonOp struct {
// A function that can be used to log debug information about the op. The
// first argument is a call depth.
//
// May be nil.
debugLog func(int, string, ...interface{})
// A logger to be used for logging exceptional errors.
//
// May be nil.
errorLogger *log.Logger
// A function that is invoked with the error given to Respond, for use in
@ -116,6 +120,10 @@ func (o *commonOp) Context() context.Context {
}
func (o *commonOp) Logf(format string, v ...interface{}) {
if o.debugLog == nil {
return
}
const calldepth = 2
o.debugLog(calldepth, format, v...)
}
@ -131,15 +139,19 @@ func (o *commonOp) Respond(err error) {
}
// Log the error.
o.Logf(
"-> (%s) error: %v",
o.op.ShortDesc(),
err)
if o.debugLog != nil {
o.Logf(
"-> (%s) error: %v",
o.op.ShortDesc(),
err)
}
o.errorLogger.Printf(
"(%s) error: %v",
o.op.ShortDesc(),
err)
if o.errorLogger != nil {
o.errorLogger.Printf(
"(%s) error: %v",
o.op.ShortDesc(),
err)
}
// Send a response to the kernel.
o.bazilReq.RespondError(err)
@ -157,11 +169,15 @@ func (o *commonOp) sendBazilfuseResponse(resp interface{}) {
// Special case: handle successful ops with no response struct.
if resp == nil {
o.Logf("-> (%s) OK", o.op.ShortDesc())
respond.Call([]reflect.Value{})
return
}
// Otherwise, send the response struct to the kernel.
o.Logf("-> %v", resp)
if o.debugLog != nil {
o.Logf("-> %v", resp)
}
respond.Call([]reflect.Value{reflect.ValueOf(resp)})
}

View File

@ -32,6 +32,8 @@ import (
//
// It is guaranteed that o != nil. If the op is unknown, a special unexported
// type will be used.
//
// The debug logging function and error logger may be nil.
func Convert(
opCtx context.Context,
r bazilfuse.Request,

View File

@ -16,7 +16,6 @@ package fuse
import (
"fmt"
"io/ioutil"
"log"
"runtime"
@ -193,12 +192,6 @@ func Mount(
dir string,
server Server,
config *MountConfig) (mfs *MountedFileSystem, err error) {
// Arrange for a non-nil debug logger.
debugLogger := config.DebugLogger
if debugLogger == nil {
debugLogger = log.New(ioutil.Discard, "", 0)
}
// Initialize the struct.
mfs = &MountedFileSystem{
dir: dir,
@ -206,7 +199,6 @@ func Mount(
}
// Open a bazilfuse connection.
debugLogger.Println("Opening a bazilfuse connection.")
bfConn, err := bazilfuse.Mount(mfs.dir, config.bazilfuseOptions()...)
if err != nil {
err = fmt.Errorf("bazilfuse.Mount: %v", err)
@ -219,17 +211,11 @@ func Mount(
opContext = context.Background()
}
// Create a /dev/null error logger if necessary.
errorLogger := config.ErrorLogger
if errorLogger == nil {
errorLogger = log.New(ioutil.Discard, "", 0)
}
// Create our own Connection object wrapping it.
connection, err := newConnection(
opContext,
debugLogger,
errorLogger,
config.DebugLogger,
config.ErrorLogger,
bfConn)
if err != nil {