diff --git a/changelog/unreleased/9919 b/changelog/unreleased/9919 new file mode 100644 index 00000000000..e093798ba7f --- /dev/null +++ b/changelog/unreleased/9919 @@ -0,0 +1,3 @@ +Enhancement: Reduce CPU load during discovery + +https://github.com/owncloud/client/pull/9919 diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index e810698f82c..ffeac31967a 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -127,7 +127,9 @@ Folder::Folder(const FolderDefinition &definition, connect(_engine.data(), &SyncEngine::aboutToRemoveAllFiles, this, &Folder::slotAboutToRemoveAllFiles); - connect(_engine.data(), &SyncEngine::transmissionProgress, this, &Folder::slotTransmissionProgress); + connect(_engine.data(), &SyncEngine::transmissionProgress, this, [this](const ProgressInfo &pi) { + emit ProgressDispatcher::instance()->progressInfo(this, pi); + }); connect(_engine.data(), &SyncEngine::itemCompleted, this, &Folder::slotItemCompleted); connect(_engine.data(), &SyncEngine::newBigFolder, @@ -1125,14 +1127,6 @@ void Folder::slotEmitFinishedDelayed() } } -// the progress comes without a folder and the valid path set. Add that here -// and hand the result over to the progress dispatcher. -void Folder::slotTransmissionProgress(const ProgressInfo &pi) -{ - emit progressInfo(pi); - emit ProgressDispatcher::instance()->progressInfo(this, pi); -} - // a item is completed: count the errors and forward to the ProgressDispatcher void Folder::slotItemCompleted(const SyncFileItemPtr &item) { diff --git a/src/gui/folder.h b/src/gui/folder.h index 24c879e839f..50be91d234e 100644 --- a/src/gui/folder.h +++ b/src/gui/folder.h @@ -367,7 +367,6 @@ class Folder : public QObject void syncStateChange(); void syncStarted(); void syncFinished(const SyncResult &result); - void progressInfo(const ProgressInfo &progress); void newBigFolderDiscovered(const QString &); // A new folder bigger than the threshold was discovered void syncPausedChanged(Folder *, bool paused); void canSyncChanged(); @@ -448,7 +447,6 @@ private slots: */ void slotSyncError(const QString &message, ErrorCategory category = ErrorCategory::Normal); - void slotTransmissionProgress(const ProgressInfo &pi); void slotItemCompleted(const SyncFileItemPtr &); void etagRetreived(const QByteArray &, const QDateTime &tp); diff --git a/src/gui/folderstatusmodel.cpp b/src/gui/folderstatusmodel.cpp index 244d908d36b..edf77b39878 100644 --- a/src/gui/folderstatusmodel.cpp +++ b/src/gui/folderstatusmodel.cpp @@ -93,8 +93,10 @@ void FolderStatusModel::setAccountState(AccountStatePtr accountState) info._checked = Qt::PartiallyChecked; _folders << info; - connect(f, &Folder::progressInfo, this, [f, this](const ProgressInfo &info) { - slotSetProgress(info, f); + connect(ProgressDispatcher::instance(), &ProgressDispatcher::progressInfo, this, [f, this](Folder *folder, const ProgressInfo &progress) { + if (folder == f) { + slotSetProgress(progress, f); + } }); connect(f, &Folder::newBigFolderDiscovered, this, &FolderStatusModel::slotNewBigFolder, Qt::UniqueConnection); @@ -895,38 +897,36 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress, Folder *f) auto *pi = &folder._progress; - const QVector roles = { FolderStatusDelegate::SyncProgressItemString, FolderStatusDelegate::WarningCount, Qt::ToolTipRole }; - - switch (progress.status()) { - case ProgressInfo::None: - Q_UNREACHABLE(); - case ProgressInfo::Discovery: - if (!progress._currentDiscoveredRemoteFolder.isEmpty()) { - pi->_overallSyncString = tr("Checking for changes in remote '%1'").arg(progress._currentDiscoveredRemoteFolder); - emit dataChanged(index(folderIndex), index(folderIndex), roles); - } else if (!progress._currentDiscoveredLocalFolder.isEmpty()) { - pi->_overallSyncString = tr("Checking for changes in local '%1'").arg(progress._currentDiscoveredLocalFolder); - emit dataChanged(index(folderIndex), index(folderIndex), roles); - } - break; - case ProgressInfo::Reconcile: - pi->_overallSyncString = tr("Reconciling changes"); - emit dataChanged(index(folderIndex), index(folderIndex), roles); - break; - case ProgressInfo::Propagation: - Q_FALLTHROUGH(); - case ProgressInfo::Done: - if (!progress._lastCompletedItem.isEmpty() - && Progress::isWarningKind(progress._lastCompletedItem._status)) { - pi->_warningCount++; - } + if (progress.status() == ProgressInfo::Done && !progress._lastCompletedItem.isEmpty() + && Progress::isWarningKind(progress._lastCompletedItem._status)) { + pi->_warningCount++; + } + // depending on the use of virtual files or small files this slot might be called very often. + // throttle the model updates to prevent an needlessly high cpu usage used on ui updates. + if (std::chrono::steady_clock::now() - folder._lastProgressUpdated > progressUpdateTimeOutC) { + const QVector roles = { FolderStatusDelegate::SyncProgressItemString, FolderStatusDelegate::WarningCount, Qt::ToolTipRole }; - // progress updates are expensive, throtle them - if (std::chrono::steady_clock::now() - folder._lastProgressUpdated > progressUpdateTimeOutC) { + switch (progress.status()) { + case ProgressInfo::None: + Q_UNREACHABLE(); + break; + case ProgressInfo::Discovery: + if (!progress._currentDiscoveredRemoteFolder.isEmpty()) { + pi->_overallSyncString = tr("Checking for changes in remote '%1'").arg(progress._currentDiscoveredRemoteFolder); + } else if (!progress._currentDiscoveredLocalFolder.isEmpty()) { + pi->_overallSyncString = tr("Checking for changes in local '%1'").arg(progress._currentDiscoveredLocalFolder); + } + break; + case ProgressInfo::Reconcile: + pi->_overallSyncString = tr("Reconciling changes"); + break; + case ProgressInfo::Propagation: + Q_FALLTHROUGH(); + case ProgressInfo::Done: computeProgress(progress, pi); - folder._lastProgressUpdated = std::chrono::steady_clock::now(); - emit dataChanged(index(folderIndex), index(folderIndex), roles); } + emit dataChanged(index(folderIndex), index(folderIndex), roles); + folder._lastProgressUpdated = std::chrono::steady_clock::now(); } }