From 973d3f1a4e4406b703d7f59527466c6b6d733a9e Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 24 Aug 2021 14:45:36 +0200 Subject: [PATCH] Performance tuning --- libnymea-app/models/logsmodel.cpp | 19 ++++++++--- libnymea-app/models/logsmodel.h | 2 ++ libnymea-app/models/xyseriesadapter.cpp | 19 ++++++++--- libnymea-app/models/xyseriesadapter.h | 4 +-- nymea-app/ui/components/SmartMeterChart.qml | 38 ++++++++------------- nymea-app/ui/mainviews/EnergyView.qml | 4 ++- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/libnymea-app/models/logsmodel.cpp b/libnymea-app/models/logsmodel.cpp index 4ef69603..9d301cda 100644 --- a/libnymea-app/models/logsmodel.cpp +++ b/libnymea-app/models/logsmodel.cpp @@ -159,6 +159,7 @@ void LogsModel::setTypeIds(const QStringList &typeIds) beginResetModel(); qDeleteAll(m_list); m_list.clear(); + m_generatedEntries = 0; endResetModel(); fetchMore(); } @@ -256,7 +257,7 @@ LogEntry *LogsModel::findClosest(const QDateTime &dateTime) void LogsModel::logsReply(int /*commandId*/, const QVariantMap &data) { - int offset = data.value("offset").toInt(); + int offset = data.value("offset").toInt() + m_generatedEntries; int count = data.value("count").toInt(); // qDebug() << qUtf8Printable(QJsonDocument::fromVariant(data).toJson()); @@ -266,9 +267,6 @@ void LogsModel::logsReply(int /*commandId*/, const QVariantMap &data) foreach (const QVariant &logEntryVariant, logEntries) { QVariantMap entryMap = logEntryVariant.toMap(); QDateTime timeStamp = QDateTime::fromMSecsSinceEpoch(entryMap.value("timestamp").toLongLong()); - if (!m_viewStartTime.isNull() && timeStamp < m_viewStartTime) { - continue; - } QString thingId = entryMap.value("thingId").toString(); QString typeId = entryMap.value("typeId").toString(); QMetaEnum sourceEnum = QMetaEnum::fromType(); @@ -277,8 +275,19 @@ void LogsModel::logsReply(int /*commandId*/, const QVariantMap &data) LogEntry::LoggingEventType loggingEventType = static_cast(loggingEventTypeEnum.keyToValue(entryMap.value("eventType").toByteArray())); QVariant value = loggingEventType == LogEntry::LoggingEventTypeActiveChange ? entryMap.value("active").toBool() : entryMap.value("value"); QString errorCode = entryMap.value("errorCode").toString(); + + bool stopProcessing = false; + if (m_viewStartTime.isValid() && timeStamp.addSecs(-60) < m_viewStartTime) { + timeStamp = m_viewStartTime.addSecs(-60); + stopProcessing = true; + m_generatedEntries++; + } LogEntry *entry = new LogEntry(timeStamp, value, thingId, typeId, loggingSource, loggingEventType, errorCode, this); newBlock.append(entry); +// qCDebug(dcLogEngine()) << objectName() << "adding entry at" << timeStamp << m_viewStartTime; + if (stopProcessing) { + break; + } } // qCDebug(dcLogEngine()) << objectName() << "Received logs from" << offset << "to" << offset + count << "Actual count:" << newBlock.count(); @@ -363,7 +372,7 @@ void LogsModel::fetchMore(const QModelIndex &parent) } params.insert("limit", m_blockSize); - params.insert("offset", m_list.count()); + params.insert("offset", m_list.count() - m_generatedEntries); // qDebug() << "Fetching logs from" << m_startTime.toString() << "to" << m_endTime.toString() << "with offset" << m_list.count() << "and limit" << m_blockSize; diff --git a/libnymea-app/models/logsmodel.h b/libnymea-app/models/logsmodel.h index efc07ad4..ab134137 100644 --- a/libnymea-app/models/logsmodel.h +++ b/libnymea-app/models/logsmodel.h @@ -133,6 +133,8 @@ protected: bool m_canFetchMore = true; + int m_generatedEntries = 0; + }; #endif // LOGSMODEL_H diff --git a/libnymea-app/models/xyseriesadapter.cpp b/libnymea-app/models/xyseriesadapter.cpp index a84e9e5a..66f5955f 100644 --- a/libnymea-app/models/xyseriesadapter.cpp +++ b/libnymea-app/models/xyseriesadapter.cpp @@ -163,12 +163,21 @@ void XYSeriesAdapter::logEntryAdded(LogEntry *entry) int idx = entry->timestamp().secsTo(m_newestSample) / m_sampleRate; if (idx > m_samples.count()) { - qCWarning(dcLogEngine) << "Overflowing integer size for XYSeriesAdapter!"; + qCWarning(dcLogEngine) << objectName() << "Overflowing integer size for XYSeriesAdapter!"; return; } - Sample *sample = m_samples.at(static_cast(idx)); - LogEntry *oldLast = sample->entries.count() > 0 ? sample->entries.last() : nullptr; - sample->entries.append(entry); +// qCDebug(dcLogEngine()) << objectName() << "Inserting sample at:" << idx << entry->timestamp(); + Sample *sample = m_samples.at(idx); + LogEntry *oldLast = nullptr; + // In theory we'd need to insert sorted, but only the last one actually matters for subsequent samples + // For the current sample we're calculating the median anyways, so just append/prepend t be a bit faster + if (sample->entries.count() > 0 && sample->entries.last()->timestamp() < entry->timestamp()) { + oldLast = sample->entries.last(); + sample->entries.append(entry); + } else { + sample->entries.prepend(entry); + } + LogEntry *newLast = sample->entries.last(); qreal value = calculateSampleValue(idx); m_series->replace(idx, sample->timestamp.toMSecsSinceEpoch(), value); @@ -189,7 +198,7 @@ void XYSeriesAdapter::logEntryAdded(LogEntry *entry) for (int i = idx - 1; i >= 0; i--) { Sample *nextSample = m_samples.at(i); if (nextSample->startingPoint == oldLast) { - nextSample->startingPoint = entry; + nextSample->startingPoint = newLast; qreal value = calculateSampleValue(i); // qWarning() << "Updating" << i << value; m_series->replace(i, nextSample->timestamp.toMSecsSinceEpoch(), value); diff --git a/libnymea-app/models/xyseriesadapter.h b/libnymea-app/models/xyseriesadapter.h index 001b6d12..c227502b 100644 --- a/libnymea-app/models/xyseriesadapter.h +++ b/libnymea-app/models/xyseriesadapter.h @@ -69,8 +69,8 @@ private: class Sample { public: QDateTime timestamp; // The timestamp where this sample *ends* - QList entries; // all log entries in this sample, that is, from timestamp - m_sampleRate - LogEntry *startingPoint = nullptr; // the starting point for the same. Normally the last entry of the previous sample + QList entries; // all log entries in this sample, that is, from timestamp - smaple size to timestamp + LogEntry *startingPoint = nullptr; // the starting point for the sample. Normally the last entry of the previous sample }; LogsModel* m_model = nullptr; QtCharts::QXYSeries* m_series = nullptr; diff --git a/nymea-app/ui/components/SmartMeterChart.qml b/nymea-app/ui/components/SmartMeterChart.qml index e854dc3a..5e571f1a 100644 --- a/nymea-app/ui/components/SmartMeterChart.qml +++ b/nymea-app/ui/components/SmartMeterChart.qml @@ -48,8 +48,9 @@ ChartView { property Thing rootMeter: null property ThingsProxy meters: null property int multiplier: 1 + property string stateName: "totalEnergyConsumed" - readonly property State rootMeterTotalConsumedEnergyState: rootMeter ? rootMeter.stateByName("totalEnergyConsumed") : null + readonly property State rootMeterTotalEnergyState: rootMeter ? rootMeter.stateByName(stateName) : null Connections { target: meters @@ -69,29 +70,14 @@ ChartView { pieSeries.clear(); d.sliceMap = {} - var unknownConsumerEnergy = 0; - if (rootMeter) { - unknownConsumerEnergy = rootMeter.stateByName("totalEnergyConsumed").value - } - - if (rootMeter) { - var slice = pieSeries.append(qsTr("Unknown"), unknownConsumerEnergy) - slice.color = Style.accentColor - d.sliceMap[slice] = rootMeter - } + var unknownEnergy = rootMeterTotalEnergyState ? rootMeterTotalEnergyState.value : 0 for (var i = 0; i < meters.count; i++) { var thing = meters.get(i); var value = 0; - var totalConsumedStateType = thing.thingClass.stateTypes.findByName("totalEnergyConsumed") - if (totalConsumedStateType) { - var totalConsumedState = thing.states.getState(totalConsumedStateType.id) - value = value + (totalConsumedState.value * root.multiplier) - } - var totalProducedStateType = thing.thingClass.stateTypes.findByName("totalEnergyProduced") - if (totalProducedStateType) { - var totalProducedState = thing.states.getState(totalProducedStateType.id) - value = value - (totalProducedState.value * root.multiplier) + var energyState = thing.stateByName(root.stateName) + if (energyState) { + value += energyState.value } var slice = pieSeries.append(thing.name, Math.max(0, value)) var color = Style.accentColor @@ -104,7 +90,13 @@ ChartView { } slice.color = color d.sliceMap[slice] = thing - unknownConsumerEnergy -= value + unknownEnergy -= value + } + + if (unknownEnergy > 0) { + var slice = pieSeries.append(qsTr("Unknown"), unknownEnergy) + slice.color = Style.accentColor + d.sliceMap[slice] = rootMeter } } @@ -128,8 +120,8 @@ ChartView { font.pixelSize: app.largeFont Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter - text: root.rootMeterTotalConsumedEnergyState - ? root.rootMeterTotalConsumedEnergyState.value.toFixed(2) + text: root.rootMeterTotalEnergyState + ? root.rootMeterTotalEnergyState.value.toFixed(2) : Math.round(pieSeries.sum * 1000) / 1000 } diff --git a/nymea-app/ui/mainviews/EnergyView.qml b/nymea-app/ui/mainviews/EnergyView.qml index 49181f97..8805af14 100644 --- a/nymea-app/ui/mainviews/EnergyView.qml +++ b/nymea-app/ui/mainviews/EnergyView.qml @@ -124,6 +124,7 @@ MainViewBase { } XYSeriesAdapter { id: rootMeterSeriesAdapter + objectName: "Root meter adapter" logsModel: rootMeterLogsModel sampleRate: chartView.sampleRate xySeries: rootMeterSeries @@ -197,6 +198,7 @@ MainViewBase { } property XYSeriesAdapter adapter: XYSeriesAdapter { id: seriesAdapter + objectName: consumer.thing.name + " adapter" logsModel: logsModel sampleRate: chartView.sampleRate xySeries: upperSeries @@ -441,8 +443,8 @@ MainViewBase { rootMeter: root.rootMeter meters: producers title: qsTr("Total produced energy") + stateName: "totalEnergyProduced" visible: root.rootMeter || producers.count > 0 - multiplier: -1 } } }