Run worker pool at lowest thread priority (#1497)

This commit is contained in:
Reilly Brogan 2024-09-21 00:02:51 -05:00 committed by GitHub
parent d8b075dc0c
commit edad7fad32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 110 additions and 13 deletions

View File

@ -243,6 +243,8 @@ set(SOURCES
miscellaneous/templates.h
miscellaneous/textfactory.cpp
miscellaneous/textfactory.h
miscellaneous/thread.cpp
miscellaneous/thread.h
network-web/adblock/adblockdialog.cpp
network-web/adblock/adblockdialog.h
network-web/adblock/adblockicon.cpp

View File

@ -10,6 +10,7 @@
#include "exceptions/filteringexception.h"
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/thread.h"
#include "services/abstract/cacheforserviceroot.h"
#include "services/abstract/feed.h"
#include "services/abstract/labelsnode.h"
@ -17,7 +18,6 @@
#include <QDebug>
#include <QJSEngine>
#include <QString>
#include <QThread>
#include <QtConcurrentMap>
FeedDownloader::FeedDownloader()
@ -47,7 +47,7 @@ void FeedDownloader::synchronizeAccountCaches(const QList<CacheForServiceRoot*>&
for (CacheForServiceRoot* cache : caches) {
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Synchronizing cache back to server on thread"
<< QUOTE_W_SPACE_DOT(QThread::currentThreadId());
<< QUOTE_W_SPACE_DOT(getThreadID());
cache->saveAllCachedData(false);
if (m_stopCacheSynchronization) {
@ -77,7 +77,7 @@ void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
}
else {
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Starting feed updates from worker in thread"
<< QUOTE_W_SPACE_DOT(QThread::currentThreadId());
<< QUOTE_W_SPACE_DOT(getThreadID());
// Job starts now.
emit updateStarted();
@ -155,6 +155,9 @@ void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
std::function<FeedUpdateResult(const FeedUpdateRequest&)> func =
[=](const FeedUpdateRequest& fd) -> FeedUpdateResult {
#if defined(Q_OS_LINUX)
setThreadPriority(Priority::LOWEST);
#endif
return updateThreadedFeed(fd);
};
@ -220,7 +223,7 @@ void FeedDownloader::updateOneFeed(ServiceRoot* acc,
acc->itemChanged({feed});
}
qlonglong thread_id = qlonglong(QThread::currentThreadId());
qlonglong thread_id = getThreadID();
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Downloading new messages for feed ID" << QUOTE_W_SPACE(feed->customId())
<< "URL:" << QUOTE_W_SPACE(feed->source()) << "title:" << QUOTE_W_SPACE(feed->title()) << "in thread "
@ -435,7 +438,7 @@ void FeedDownloader::updateOneFeed(ServiceRoot* acc,
void FeedDownloader::finalizeUpdate() {
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Finished feed updates in thread"
<< QUOTE_W_SPACE_DOT(QThread::currentThreadId());
<< QUOTE_W_SPACE_DOT(getThreadID());
m_feeds.clear();

View File

@ -4,14 +4,14 @@
#include "database/databasequeries.h"
#include "miscellaneous/application.h"
#include "miscellaneous/thread.h"
#include <QDebug>
#include <QThread>
DatabaseCleaner::DatabaseCleaner(QObject* parent) : QObject(parent) {}
void DatabaseCleaner::purgeDatabaseData(CleanerOrders which_data) {
qDebugNN << LOGSEC_DB << "Performing database cleanup in thread:" << QUOTE_W_SPACE_DOT(QThread::currentThreadId());
qDebugNN << LOGSEC_DB << "Performing database cleanup in thread:" << QUOTE_W_SPACE_DOT(getThreadID());
// Inform everyone about the start of the process.
emit purgeStarted();

View File

@ -5,6 +5,7 @@
#include "definitions/definitions.h"
#include "exceptions/applicationexception.h"
#include "miscellaneous/iofactory.h"
#include "miscellaneous/thread.h"
#include <QDir>
#include <QSqlError>
@ -14,7 +15,7 @@
DatabaseDriver::DatabaseDriver(QObject* parent) : QObject(parent) {}
QSqlDatabase DatabaseDriver::threadSafeConnection(const QString& connection_name, DesiredStorageType desired_type) {
qlonglong thread_id = qlonglong(QThread::currentThreadId());
qlonglong thread_id = getThreadID();
bool is_main_thread = QThread::currentThread() == qApp->thread();
QSqlDatabase database =

View File

@ -27,6 +27,7 @@
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/mutex.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/thread.h"
#include "network-web/adblock/adblockicon.h"
#include "network-web/adblock/adblockmanager.h"
#include "network-web/webfactory.h"
@ -38,7 +39,6 @@
#include <QFileDialog>
#include <QRect>
#include <QScopedPointer>
#include <QThread>
#include <QTimer>
#include <QToolButton>
#include <QWidgetAction>
@ -54,7 +54,7 @@
FormMain::FormMain(QWidget* parent, Qt::WindowFlags f)
: QMainWindow(parent, f), m_ui(new Ui::FormMain), m_trayMenu(nullptr), m_statusBar(nullptr) {
qDebugNN << LOGSEC_GUI
<< "Creating main application form in thread:" << QUOTE_W_SPACE_DOT(QThread::currentThreadId());
<< "Creating main application form in thread:" << QUOTE_W_SPACE_DOT(getThreadID());
// setAttribute(Qt::WA_WindowPropagation, true);
m_ui->setupUi(this);
qApp->setMainForm(this);

View File

@ -42,7 +42,7 @@ TextBrowserViewer::TextBrowserViewer(QWidget* parent)
setDocument(m_document.data());
m_resourceDownloader->moveToThread(m_resourceDownloaderThread);
m_resourceDownloaderThread->start();
m_resourceDownloaderThread->start(QThread::LowPriority);
connect(this, &TextBrowserViewer::reloadDocument, this, [this]() {
const auto scr = verticalScrollBarPosition();

View File

@ -1157,6 +1157,12 @@ void Application::setupWorkHorsePool() {
m_workHorsePool->setMaxThreadCount((std::min)(MAX_THREADPOOL_THREADS, 2 * ideal_th_count));
}
#if QT_VERSION_MAJOR == 6
// Avoid competing with interactive processes/threads by running the
// worker pool at a very low priority
m_workHorsePool->setThreadPriority(QThread::LowestPriority);
#endif
// NOTE: Do not expire threads so that their IDs are not reused.
// This fixes cross-thread QSqlDatabase access.
m_workHorsePool->setExpiryTimeout(-1);

View File

@ -128,7 +128,7 @@ void FeedReader::initializeFeedDownloader() {
connect(m_feedDownloader, &FeedDownloader::updateStarted, this, &FeedReader::feedUpdatesStarted);
connect(m_feedDownloader, &FeedDownloader::updateFinished, qApp->feedUpdateLock(), &Mutex::unlock);
m_feedDownloaderThread->start();
m_feedDownloaderThread->start(QThread::LowPriority);
}
}

View File

@ -0,0 +1,67 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "definitions/definitions.h"
#include "miscellaneous/thread.h"
#include <QThread>
#if defined(Q_OS_LINUX)
#include <sched.h>
#include <sys/resource.h>
#include <unistd.h>
#endif
// Returns the thread ID of the caller
qlonglong getThreadID() {
#if defined(Q_OS_LINUX)
return qlonglong(gettid());
#else
return qlonglong(QThread::currentThreadId());
#endif
}
#if defined(Q_OS_LINUX)
// On Linux QThread priorities do nothing with the default scheduler SCHED_OTHER
// Set the nice value manually in this case until Qt supports nice values
void setThreadPriority(Priority prio) {
int current_policy = sched_getscheduler(0);
if (current_policy != -1) {
// If the current scheduling policy is neither of these the QThread priority should be working
if (current_policy != SCHED_BATCH && current_policy != SCHED_OTHER) {
return;
}
// Set the scheduler to SCHED_BATCH if needed, indicating that this process is non-interactive
if (current_policy == SCHED_OTHER) {
struct sched_param p = {0};
if (sched_setscheduler(0, SCHED_BATCH, &p) != 0) {
qDebugNN << "Setting the scheduler to SCHED_BATCH for thread"
<< QUOTE_W_SPACE(getThreadID())
<< "failed with error" << QUOTE_W_SPACE_DOT(errno);
// We can still try to set the nice value
}
}
errno = 0; // Clear errno since -1 is a legitimate return value
int current_priority = getpriority(PRIO_PROCESS, 0);
if (errno != 0) {
qDebugNN << "Getting the priority for thread"
<< QUOTE_W_SPACE(getThreadID())
<< "failed with error" << QUOTE_W_SPACE_DOT(errno);
} else {
if (current_priority != prio) {
setpriority(PRIO_PROCESS, 0, prio);
if (errno != 0) {
qDebugNN << "Setting the priority for thread"
<< QUOTE_W_SPACE(getThreadID())
<< "failed with error" << QUOTE_W_SPACE_DOT(errno);
}
}
}
} else {
qDebugNN << "Getting the priority for thread"
<< QUOTE_W_SPACE(getThreadID())
<< "failed with error" << QUOTE_W_SPACE_DOT(errno);
}
}
#endif

View File

@ -0,0 +1,19 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef THREAD_H
#define THREAD_H
qlonglong getThreadID();
#if defined(Q_OS_LINUX)
// Values corresponding to nice values
enum Priority {
LOWEST = 19,
LOW = 10,
NORMAL = 0
};
void setThreadPriority(Priority);
#endif
#endif // THREAD_H

View File

@ -23,7 +23,6 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QThread>
#include <QTimer>
#include <QUrlQuery>