Save hosts on a separate thread

QSettings on macOS Ventura performs horribly when saving a lot of values
(like several hosts or a host with a large app list). This change considerably
improves UI performance by moving the long operation off the main thread.
This commit is contained in:
Cameron Gutman 2022-10-25 00:00:36 -05:00
parent cb04925c6e
commit cebd3bf751
2 changed files with 39 additions and 12 deletions

View file

@ -147,7 +147,8 @@ ComputerManager::ComputerManager(QObject *parent)
: QObject(parent),
m_PollingRef(0),
m_MdnsBrowser(nullptr),
m_CompatFetcher(nullptr)
m_CompatFetcher(nullptr),
m_HostsListDirty(false)
{
QSettings settings;
@ -202,19 +203,43 @@ ComputerManager::~ComputerManager()
}
}
class DeferredHostSaveTask : public QRunnable
{
public:
DeferredHostSaveTask(ComputerManager* cm)
: m_ComputerManager(cm) {}
void run()
{
// Only persist the host list if it was dirty.
//
// NB: We can have multiple save tasks queued up and so another one could
// have persisted the changes already.
if (m_ComputerManager->m_HostsListDirty.testAndSetAcquire(true, false)) {
QReadLocker lock(&m_ComputerManager->m_Lock);
QSettings settings;
settings.remove(SER_HOSTS);
settings.beginWriteArray(SER_HOSTS);
int i = 0;
for (const NvComputer* computer : m_ComputerManager->m_KnownHosts) {
settings.setArrayIndex(i++);
computer->serialize(settings);
}
settings.endArray();
}
}
private:
ComputerManager* m_ComputerManager;
};
void ComputerManager::saveHosts()
{
QSettings settings;
QReadLocker lock(&m_Lock);
settings.remove(SER_HOSTS);
settings.beginWriteArray(SER_HOSTS);
int i = 0;
for (const NvComputer* computer : m_KnownHosts) {
settings.setArrayIndex(i++);
computer->serialize(settings);
}
settings.endArray();
// Punt to a worker thread because QSettings on macOS can take ages (> 500 ms)
// to persist our host list to disk (especially when a host has a bunch of apps).
m_HostsListDirty.storeRelease(true);
QThreadPool::globalInstance()->start(new DeferredHostSaveTask(this));
}
QHostAddress ComputerManager::getBestGlobalAddressV6(QVector<QHostAddress> &addresses)

View file

@ -167,6 +167,7 @@ class ComputerManager : public QObject
friend class DeferredHostDeletionTask;
friend class PendingAddTask;
friend class PendingPairingTask;
friend class DeferredHostSaveTask;
public:
explicit ComputerManager(QObject *parent = nullptr);
@ -228,4 +229,5 @@ private:
QMdnsEngine::Cache m_MdnsCache;
QVector<MdnsPendingComputer*> m_PendingResolution;
CompatFetcher m_CompatFetcher;
QAtomicInteger<bool> m_HostsListDirty;
};