Performance issues with multiple visible Windows
-
The swap partition is used when application are starting to use up all amiable memory, the system then start to swap in/out memory pages between the RAM and the partition on the hard drive.
By the way, why a QTreeView ? Are you using any feature from it ?
@SGaist
Ah ok, now I get what you mean with swap.I used QTreeView because 1) It seems to perform better, 2) the default look works in my favor (I don't want the borders of the table).
As my current system has active 12GB ram, that shouldn't be that much of a problem. Furthermore, I once ran the application to 100'000 log entries for each of the 20 Clients and it went up to 2GB~. With the logLimit of 10'000 logs per Model memory shouldn't become much of a problem.
-
Wouldn't a QListView do what you want ?
-
For filtering or just for formatting ?
-
In your custom model, are you returning the minimal from your
data
method ? -
Tha's how my current data function looks in my model:
QVariant CustomTableModel::data(const QModelIndex & index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() >= listOfEntries.size() || index.row() < 0) return QVariant(); if (role == Qt::DisplayRole) { if (index.column() < 0 || index.column() > 6) return QVariant(); if(index.column() == 0) { return QString::number(index.row()); } return listOfEntries.at(index.row()).at(index.column()-1); } return QVariant(); }
-
Looks good.
IIRC, you can avoid the
QString::number
call and just returnindex.row()
or something along the lines of:QVariant CustomTableModel::data(const QModelIndex & index, int role) const { if (!index.isValid() || role != Qt::DisplayRole) return QVariant(); const int column = index.column(); const int row = index.row(); if (column < 0 || column > 6) return QVariant(); if(column == 0) { return row; } else { return listOfEntries.at(row).at(column-1); } return QVariant(); }
-
For those who are interested, I now how a working solution, thanks to the help of my advisors at the HSR.
As the main problem lay with the updating of multiple views, I first tried to change updates to bulk updates, with an updater thread signaling when to update the GUI.
Meaning:- A CaptureWorker in a Thread gathered logs until it was signalled by
- A UpdateWorker, which in a set amount of time, sent an "update" signal to the CaptureWorker, which in turn signaled, with the logs,
- RT_Main, ie., my MainWindow's handleProcessedLogs
This meant, that for example every 200ms multiple clients where updated at once.
The problem that issued from this solution, was that too many update view signals where created at the same time, which froze the GUI.
The new solution basically spreads the updates in the given interval on a per client basis, ie. there are still 20 Clients updated within the 200ms interval, but now they are progressively updated during the 200ms intervall and not at once every 200ms. The current solution looks like this:
Main Window:
void RT_Main::handleProcessedLogs(const QString & clientName, const QList<QList<QString>> & rows) const { handleClientLog(modell.getConstClient(clientName), rows); } void RT_Main::handleClientLog(const RT_Client& client, const QList<QList<QString>>& logs) const { if (client.live()) { client.addLog(logs); } if (client.toFile() || client.toRingFile()) { signalToFileLog(logs, client); } if (client.getClientId() != RT_Constants::GLOBAL_ID && client.toParent()) { handleClientLog(modell.getConstGroupClient(client.getGroupName()), logs); } if (client.toGlobal()) { modell.globalClient.addLog(logs); } } void RT_Main::adjustUpdateInterval() { int windowCount = modell.getWindowedClientsCount(); modell.updateInterval(windowCount > 1 ? RT_Constants::baseUpdateInterval + windowCount * (RT_Constants::baseUpdateInterval / 4) : RT_Constants::baseUpdateInterval); }
The adjustUpdateIntervall is called whenever a window is created or closed, there is a base Interval, ie. the lowest update frequency, whcih is at 200ms when there are no additional log windows, and gets increased with every new window (ie. UpdateWorker's signal interval ranges from 200ms to 1250ms at 0 - 20 Windows). The modell.updateInterval is thread-safe, ie. Mutex-Locked for writing. Maybe I should do one for reading as well?
My CaptureWorker, where logs are processed and gathered until and update signal arrives:
void RT_CaptureWorker::signalLogsReady() { if(!entries.isEmpty()) { int sleepTime = modell.updateInterval() / entries.keys().count(); for (const auto & key : entries.keys()) { emit logsProcessed(key, *entries.constFind(key)); QThread::msleep(sleepTime); } entries.clear(); } } void RT_CaptureWorker::handleLog(const QString & clientName, const QString & groupName, const REP::PROTO::LogMsg & msg) { if (entries.contains(clientName)) { entries[clientName].append(CommonLogUtils::prepareLogEntry(clientName, groupName, msg)); } else { entries.insert(clientName, QList<QList<QString>>{CommonLogUtils::prepareLogEntry(clientName, groupName, msg)}); } }
The UpdateWorker, which in given intervals, signals the CaptureWorker to update:
inline void RT_UpdateWorker::startUpdater() { while(true) { emit signalUpdate(); QThread::msleep(modell.updateInterval()); } }
I hope this "approach" may be an inspiration for others who struggled with a similar problem. I'm open for any further improvements!
-
One other thing you might want to try: replace your 2 dimensional QList with 2 dimensional QVector.