From 652d3cdee4b505b34556269cf1a8b878a8d9f3c2 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 10 Nov 2022 18:00:32 +0000 Subject: [PATCH] vfs: windows: fix slow opening of exe files by not truncating files when not necessary Before this change we truncated files in the backing store regardless of whether we needed to or not. After, we check to see if the file is the right size and don't truncate if it is. Apparently Windows Defender likes to check executables each time they are modified, and truncating a file to its existing size is enough to trigger the Windows Defender scan. This was causing a big slowdown for operations which opened and closed the file a lot, such as looking at properties on an executable. See: https://forum.rclone.org/t/for-mount-sftp-why-right-click-on-exe-file-is-so-slow-until-it-freezes/33830 --- vfs/vfscache/item.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/vfs/vfscache/item.go b/vfs/vfscache/item.go index b7f40252d..262f19104 100644 --- a/vfs/vfscache/item.go +++ b/vfs/vfscache/item.go @@ -272,11 +272,25 @@ func (item *Item) _truncate(size int64) (err error) { } } - fs.Debugf(item.name, "vfs cache: truncate to size=%d", size) + // Check to see what the current size is, and don't truncate + // if it is already the correct size. + // + // Apparently Windows Defender likes to check executables each + // time they are modified, and truncating a file to its + // existing size is enough to trigger the Windows Defender + // scan. This was causing a big slowdown for operations which + // opened and closed the file a lot, such as looking at + // properties on an executable. + fi, err := fd.Stat() + if err == nil && fi.Size() == size { + fs.Debugf(item.name, "vfs cache: truncate to size=%d (not needed as size correct)", size) + } else { + fs.Debugf(item.name, "vfs cache: truncate to size=%d", size) - err = fd.Truncate(size) - if err != nil { - return fmt.Errorf("vfs cache: truncate: %w", err) + err = fd.Truncate(size) + if err != nil { + return fmt.Errorf("vfs cache: truncate: %w", err) + } } item.info.Size = size @@ -460,7 +474,9 @@ func (item *Item) _createFile(osPath string) (err error) { return errors.New("vfs cache item: internal error: didn't Close file") } item.modified = false + // t0 := time.Now() fd, err := file.OpenFile(osPath, os.O_RDWR, 0600) + // fs.Debugf(item.name, "OpenFile took %v", time.Since(t0)) if err != nil { return fmt.Errorf("vfs cache item: open failed: %w", err) }