From b8ca489b044590a50c864e33a209d00e5dfa54de Mon Sep 17 00:00:00 2001 From: cwiede <62332054+cwiede@users.noreply.github.com> Date: Thu, 22 Oct 2020 21:24:02 +0200 Subject: [PATCH] fix load display in case of differences in first timestamps of threads --- nexxT/services/SrvProfiling.py | 16 +++++++++------- nexxT/services/gui/Profiling.py | 13 +++++++++---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/nexxT/services/SrvProfiling.py b/nexxT/services/SrvProfiling.py index beeeb0a..7cf4625 100644 --- a/nexxT/services/SrvProfiling.py +++ b/nexxT/services/SrvProfiling.py @@ -81,7 +81,6 @@ class ThreadSpecificProfItem: def __init__(self): self._lastThreadTime = time.thread_time_ns() self._lastMonotonicTime = time.monotonic_ns() - self._firstMonotonicTime = time.monotonic_ns() self._portProfiling = {} self._portStack = [] self._measurements = [] @@ -96,12 +95,12 @@ def update(self): load = (thread_time - self._lastThreadTime) / (monotonic_time - self._lastMonotonicTime) self._lastThreadTime = thread_time self._lastMonotonicTime = monotonic_time - self._measurements.append((1e-9*(monotonic_time - self._firstMonotonicTime), load)) + self._measurements.append((monotonic_time, load)) def getLoad(self): """ Returns the load measurements. - :return: list of 2-tuples (time_seconds, load_ratio) + :return: list of 2-tuples (time_nano_seconds, load_ratio) """ res = self._measurements self._measurements = [] @@ -159,7 +158,7 @@ class ProfilingService(QObject): """ # this signal is emitted when there is new load data for a thread. - loadDataUpdated = Signal(str, QByteArray) + loadDataUpdated = Signal(str, QByteArray, QByteArray) spanDataUpdated = Signal(str, str, QByteArray) threadDeregistered = Signal(str) stopTimers = Signal() @@ -289,9 +288,12 @@ def _emitData(self): # emit each 100 ms self._lastEmitTime = t for t in self._threadSpecificProfiling: - load = np.array(self._threadSpecificProfiling[t].getLoad(), dtype=np.float32) - if load.size > 0: - self.loadDataUpdated.emit(t.objectName(), QByteArray(load.tobytes())) + load = self._threadSpecificProfiling[t].getLoad() + atimstamps = np.array([l[0] for l in load], dtype=np.int64) + aload = np.array([l[1] for l in load], dtype=np.float32) + if aload.size > 0: + self.loadDataUpdated.emit(t.objectName(), QByteArray(atimstamps.tobytes()), + QByteArray(aload.tobytes())) port_spans = self._threadSpecificProfiling[t].getSpans() for port, spans in port_spans.items(): spans = np.array(spans, dtype=np.int64) diff --git a/nexxT/services/gui/Profiling.py b/nexxT/services/gui/Profiling.py index 352d10c..eef8e45 100644 --- a/nexxT/services/gui/Profiling.py +++ b/nexxT/services/gui/Profiling.py @@ -23,6 +23,8 @@ class LoadDisplayWidget(QWidget): """ This widget displays the thread-specific load. """ + baseTimestamp = None + def __init__(self, parent): super().__init__(parent=parent) self._loadData = {} @@ -30,19 +32,22 @@ def __init__(self, parent): self.setAutoFillBackground(True) @Slot(str, QByteArray) - def newLoadData(self, threadName, loadData): + def newLoadData(self, threadName, timestamps, load): """ Slot called when new load data is available :param threadName: the name of the thread given as string :param loadData: the load data, given as the QByteArray of a n x 2 np.float32 array :return: """ - loadData = np.reshape(np.frombuffer(memoryview(loadData), dtype=np.float32), (-1, 2)) + atimestamps = np.frombuffer(memoryview(timestamps), dtype=np.int64) + aload = np.frombuffer(memoryview(load), dtype=np.float32) + if LoadDisplayWidget.baseTimestamp is None: + LoadDisplayWidget.baseTimestamp = np.min(atimestamps) if threadName not in self._loadData: self._loadData[threadName] = QPolygonF() p = self._loadData[threadName] - for i in range(loadData.shape[0]): - p.append(QPointF(loadData[i, 0], loadData[i, 1])) + for i in range(aload.shape[0]): + p.append(QPointF(1e-9*(atimestamps[i] - self.baseTimestamp), aload[i])) if p[p.count()-1].x() - p[0].x() > 60: for i in range(p.count()): if p[p.count()-1].x() - p[i].x() <= 60: