From bd37f6da17577d61b4a08de543dc46275f18dfc4 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Tue, 5 Mar 2019 21:32:37 +0100 Subject: [PATCH] lib/model: Optimize dbUpdaterRoutine (#5576) --- lib/model/folder_sendrecv.go | 77 ++++++++++++++---------------------- 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go index 4fd2534ad..783b5c3d0 100644 --- a/lib/model/folder_sendrecv.go +++ b/lib/model/folder_sendrecv.go @@ -1607,42 +1607,15 @@ func (f *sendReceiveFolder) Jobs() ([]string, []string) { func (f *sendReceiveFolder) dbUpdaterRoutine(dbUpdateChan <-chan dbUpdateJob) { const maxBatchTime = 2 * time.Second - batch := make([]dbUpdateJob, 0, maxBatchSizeFiles) - files := make([]protocol.FileInfo, 0, maxBatchSizeFiles) + batch := newFileInfoBatch(nil) tick := time.NewTicker(maxBatchTime) defer tick.Stop() changedDirs := make(map[string]struct{}) + found := false + var lastFile protocol.FileInfo - handleBatch := func() { - found := false - var lastFile protocol.FileInfo - - for _, job := range batch { - files = append(files, job.file) - - switch job.jobType { - case dbUpdateHandleFile, dbUpdateShortcutFile: - changedDirs[filepath.Dir(job.file.Name)] = struct{}{} - case dbUpdateHandleDir: - changedDirs[job.file.Name] = struct{}{} - case dbUpdateHandleSymlink, dbUpdateInvalidate: - // fsyncing symlinks is only supported by MacOS - // and invalidated files are db only changes -> no sync - } - - if job.file.IsInvalid() || (job.file.IsDirectory() && !job.file.IsSymlink()) { - continue - } - - if job.jobType&(dbUpdateHandleFile|dbUpdateDeleteFile) == 0 { - continue - } - - found = true - lastFile = job.file - } - + batch.flushFn = func(files []protocol.FileInfo) error { // sync directories for dir := range changedDirs { delete(changedDirs, dir) @@ -1663,13 +1636,12 @@ func (f *sendReceiveFolder) dbUpdaterRoutine(dbUpdateChan <-chan dbUpdateJob) { if found { f.model.receivedFile(f.folderID, lastFile) + found = false } - batch = batch[:0] - files = files[:0] + return nil } - batchSizeBytes := 0 loop: for { select { @@ -1678,26 +1650,35 @@ loop: break loop } - job.file.Sequence = 0 - batch = append(batch, job) - - batchSizeBytes += job.file.ProtoSize() - if len(batch) == maxBatchSizeFiles || batchSizeBytes > maxBatchSizeBytes { - handleBatch() - batchSizeBytes = 0 + switch job.jobType { + case dbUpdateHandleFile, dbUpdateShortcutFile: + changedDirs[filepath.Dir(job.file.Name)] = struct{}{} + case dbUpdateHandleDir: + changedDirs[job.file.Name] = struct{}{} + case dbUpdateHandleSymlink, dbUpdateInvalidate: + // fsyncing symlinks is only supported by MacOS + // and invalidated files are db only changes -> no sync } + // For some reason we seem to care about file deletions and + // content modification, but not about metadata and dirs/symlinks. + if !job.file.IsInvalid() && job.jobType&(dbUpdateHandleFile|dbUpdateDeleteFile) != 0 { + found = true + lastFile = job.file + } + + job.file.Sequence = 0 + + batch.append(job.file) + + batch.flushIfFull() + case <-tick.C: - if len(batch) > 0 { - handleBatch() - batchSizeBytes = 0 - } + batch.flush() } } - if len(batch) > 0 { - handleBatch() - } + batch.flush() } // pullScannerRoutine aggregates paths to be scanned after pulling. The scan is