Skip to content

Commit

Permalink
Run worker pool at lowest thread priority (#1497)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReillyBrogan authored Sep 21, 2024
1 parent d8b075d commit edad7fa
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/librssguard/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 8 additions & 5 deletions src/librssguard/core/feeddownloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
#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"

#include <QDebug>
#include <QJSEngine>
#include <QString>
#include <QThread>
#include <QtConcurrentMap>

FeedDownloader::FeedDownloader()
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
};

Expand Down Expand Up @@ -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 "
Expand Down Expand Up @@ -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();

Expand Down
4 changes: 2 additions & 2 deletions src/librssguard/database/databasecleaner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion src/librssguard/database/databasedriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "definitions/definitions.h"
#include "exceptions/applicationexception.h"
#include "miscellaneous/iofactory.h"
#include "miscellaneous/thread.h"

#include <QDir>
#include <QSqlError>
Expand All @@ -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 =
Expand Down
4 changes: 2 additions & 2 deletions src/librssguard/gui/dialogs/formmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -38,7 +39,6 @@
#include <QFileDialog>
#include <QRect>
#include <QScopedPointer>
#include <QThread>
#include <QTimer>
#include <QToolButton>
#include <QWidgetAction>
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
6 changes: 6 additions & 0 deletions src/librssguard/miscellaneous/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/librssguard/miscellaneous/feedreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
67 changes: 67 additions & 0 deletions src/librssguard/miscellaneous/thread.cpp
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions src/librssguard/miscellaneous/thread.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 0 additions & 1 deletion src/librssguard/network-web/adblock/adblockmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QThread>
#include <QTimer>
#include <QUrlQuery>

Expand Down

0 comments on commit edad7fa

Please sign in to comment.