From ae52e5db300d6b5cf24af8c503ec497bdb79cb29 Mon Sep 17 00:00:00 2001 From: Cubiking Date: Thu, 19 Mar 2026 17:14:46 +0000 Subject: [PATCH] Move autosave file I/O to background thread to reduce UI stutter --- src/project/internal/notationproject.cpp | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/project/internal/notationproject.cpp b/src/project/internal/notationproject.cpp index b8d618e32538b..4c1e583566040 100644 --- a/src/project/internal/notationproject.cpp +++ b/src/project/internal/notationproject.cpp @@ -49,6 +49,8 @@ #include "projectfileinfoprovider.h" #include "projecterrors.h" +#include "global/concurrency/concurrent.h" + #include "defer.h" #include "log.h" @@ -700,6 +702,35 @@ Ret NotationProject::doSave(const muse::io::path_t& path, engraving::MscIoMode i } if (maybeOutBuf) { +#ifdef MUSE_THREADS_SUPPORT + if (isAutosave) { + // For autosave, write to disk on a background thread to avoid stuttering. + // The buffer is fully serialized at this point so it's safe to move off the main thread. + muse::ByteArray data = maybeOutBuf->data(); + QString savePathCopy = savePath; + QString targetContainerPathCopy = targetContainerPath; + muse::io::path_t targetMainFilePathCopy = targetMainFilePath; + auto fs = fileSystem(); + Concurrent::run([fs, savePathCopy, targetContainerPathCopy, targetMainFilePathCopy, data]() { + Ret writeRet = fs->writeFile(savePathCopy, data); + if (!writeRet) { + LOGE() << "Autosave: failed to write project file: " << writeRet.toString(); + return; + } + Ret copyRet = fs->copy(savePathCopy, targetContainerPathCopy, true); + if (!copyRet) { + LOGE() << "Autosave: failed to copy to target: " << copyRet.toString(); + return; + } + fs->remove(savePathCopy); + QFile::setPermissions(targetMainFilePathCopy.toQString(), + QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther); + LOGD() << "Autosave: background write complete: " << targetContainerPathCopy; + }); + return make_ret(Ret::Code::Ok); + } +#endif + ret = fileSystem()->writeFile(savePath, maybeOutBuf->data()); if (!ret) { LOGE() << "Failed to write project file";