From 175240909f94936074ca8bae11337fef6a0b3313 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Thu, 23 Jul 2015 14:20:35 +1000 Subject: [PATCH] Stop over-allocating receive buffers for large writes. The maxWrite constant used to size buffers was 16 MiB, even though InitRequest.Respond always tells the kernel we want writes of 128 KiB. Caveat: mount_darwin.go implies that on darwin we were still telling the kernel 16 MiB, but experimentally it was capping this to 1 MiB. Now use exactly those sizes on those operating systems. On FreeBSD continue to use 128 KiB, because I'm not sure what it does. Allocating and zeroing buffers in allocMessage is a large source of CPU usage in a read-heavy load; I believe this change will help there. --- fuse.go | 5 +---- mount_darwin.go | 5 +++++ mount_freebsd.go | 3 +++ mount_linux.go | 4 ++++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/fuse.go b/fuse.go index ca988967..8cfe149d 100644 --- a/fuse.go +++ b/fuse.go @@ -235,7 +235,7 @@ func initMount(c *Conn, conf *mountConfig) error { s := &InitResponse{ Library: proto, MaxReadahead: conf.maxReadahead, - MaxWrite: 128 * 1024, + MaxWrite: maxWrite, Flags: InitBigWrites | conf.initFlags, } r.Respond(s) @@ -403,9 +403,6 @@ func (h *Header) RespondError(err error) { h.respond(buf) } -// Maximum file write size we are prepared to receive from the kernel. -const maxWrite = 16 * 1024 * 1024 - // All requests read from the kernel, without data, are shorter than // this. var maxRequestSize = syscall.Getpagesize() diff --git a/mount_darwin.go b/mount_darwin.go index ef09bb78..73513f84 100644 --- a/mount_darwin.go +++ b/mount_darwin.go @@ -13,6 +13,11 @@ import ( "syscall" ) +// OS X appears to cap the size of writes to 1 MiB. This constant is also used +// for sizing receive buffers, so make it as small as it can be without +// limiting write sizes. +const maxWrite = 1 << 20 + var ( errNoAvail = errors.New("no available fuse devices") errNotLoaded = errors.New("osxfuse is not loaded") diff --git a/mount_freebsd.go b/mount_freebsd.go index 70bb4102..26d884c4 100644 --- a/mount_freebsd.go +++ b/mount_freebsd.go @@ -10,6 +10,9 @@ import ( "syscall" ) +// Maximum file write size we are prepared to receive from the kernel. +const maxWrite = 128 * 1024 + func handleMountFusefsStderr(errCh chan<- error) func(line string) (ignore bool) { return func(line string) (ignore bool) { const ( diff --git a/mount_linux.go b/mount_linux.go index 197d1044..03a50ef4 100644 --- a/mount_linux.go +++ b/mount_linux.go @@ -11,6 +11,10 @@ import ( "syscall" ) +// Maximum file write size we are prepared to receive from the kernel. Linux +// appears to limit writes to 128 KiB. +const maxWrite = 128 * 1024 + func handleFusermountStderr(errCh chan<- error) func(line string) (ignore bool) { return func(line string) (ignore bool) { if line == `fusermount: failed to open /etc/fuse.conf: Permission denied` {