[multimedia/kwave] libgui: OverviewCache: combined state/min/max into one struct to reduce hash table lookups

Thomas Eschenbacher <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 2bfc70984c4791cdae3ad14a707694e0570679ae by Thomas Eschenbacher.
Committed on 25/07/2026 at 13:48.
Pushed by eschenbacher into branch 'master'.

OverviewCache: combined state/min/max into one struct to reduce hash table lookups

M  +35   -52   libgui/OverViewCache.cpp
M  +15   -8    libgui/OverViewCache.h

https://invent.kde.org/multimedia/kwave/-/commit/2bfc70984c4791cdae3ad14a707694e0570679ae

diff --git a/libgui/OverViewCache.cpp b/libgui/OverViewCache.cpp
index 24e32be4..22db0e39 100644
--- a/libgui/OverViewCache.cpp
+++ b/libgui/OverViewCache.cpp
@@ -37,7 +37,8 @@ Kwave::OverViewCache::OverViewCache(Kwave::SignalManager &signal,
                                     const QVector<unsigned int> *src_tracks)
     :m_signal(signal),
      m_selection(&signal, src_offset, src_length, src_tracks),
-     m_min(), m_max(), m_state(), m_minmax(),
+     m_track_state(),
+     m_minmax(),
      m_scale(1),
      m_lock()
 {
@@ -64,10 +65,7 @@ Kwave::OverViewCache::OverViewCache(Kwave::SignalManager &signal,
 Kwave::OverViewCache::~OverViewCache()
 {
     QMutexLocker lock(&m_lock);
-
-    m_state.clear();
-    m_min.clear();
-    m_max.clear();
+    m_track_state.clear();
 }
 
 //***************************************************************************
@@ -85,23 +83,21 @@ void Kwave::OverViewCache::scaleUp()
     if (shrink <= 1) return; // nothing to shrink, just ignore new scale
 
     // loop over all tracks
-    for (QHash<quint64, QVector <CacheState> >::iterator
-        it(m_state.begin()); it != m_state.end(); ++it)
+    for (auto ts : m_track_state)
     {
-        const quint64 uid = it.key();
         unsigned int dst = 0;
         unsigned int count = CACHE_SIZE / shrink;
         Q_ASSERT(count <= CACHE_SIZE);
 
         // source pointers
-        sample_t *smin = m_min[uid].data();
-        sample_t *smax = m_max[uid].data();
-        CacheState *sstate = it.value().data();
+        CacheState *sstate = ts.m_state.data();
+        sample_t   *smin   = ts.m_min.data();
+        sample_t   *smax   = ts.m_max.data();
 
         // destination pointers
-        sample_t *dmin = smin;
-        sample_t *dmax = smax;
         CacheState *dstate = sstate;
+        sample_t   *dmin   = smin;
+        sample_t   *dmax   = smax;
 
         // loop over all entries to be shrunk
         while (dst < count) {
@@ -154,8 +150,9 @@ void Kwave::OverViewCache::invalidateCache(quint64 track_id,
 {
     if (track_id) {
         // invalidate a single track
-        Q_ASSERT(m_state.contains(track_id));
-        if (!m_state.contains(track_id)) return;
+        QHash<quint64, TrackState>::iterator it = m_track_state.find(track_id);
+        Q_ASSERT(it != m_track_state.end());
+        if (it == m_track_state.end()) return;
 
         if (last >= CACHE_SIZE) last = CACHE_SIZE - 1;
 
@@ -164,14 +161,13 @@ void Kwave::OverViewCache::invalidateCache(quint64 track_id,
 //             first, last);
 
         for (unsigned int pos = first; pos <= last; ++pos)
-            m_state[track_id][pos] = Invalid;
+            (*it).m_state[pos] = Invalid;
     } else {
         // invalidate all tracks
-        for (QHash<quint64, QVector <CacheState> >::const_iterator
-            it(m_state.constBegin()); it != m_state.constEnd(); ++it)
+        for (QHash<quint64, TrackState>::key_iterator
+            it(m_track_state.keyBegin()); it != m_track_state.keyEnd(); ++it)
         {
-            const quint64 uid = it.key();
-            invalidateCache(uid, first, last);
+            invalidateCache(*it, first, last);
         }
     }
 }
@@ -187,17 +183,11 @@ void Kwave::OverViewCache::slotTrackInserted(quint64 track_id)
     if ((m_selection.length() / m_scale) < (CACHE_SIZE / 4))
         scaleDown();
 
-    QVector<CacheState> state(CACHE_SIZE);
-    QVector<sample_t> min(CACHE_SIZE);
-    QVector<sample_t> max(CACHE_SIZE);
-
-    min.fill(SAMPLE_MAX);
-    max.fill(SAMPLE_MIN);
-    state.fill(Unused);
-
-    m_min.insert(track_id, min);
-    m_max.insert(track_id, max);
-    m_state.insert(track_id, state);
+    m_track_state.insert(track_id, {
+        QVector<CacheState>(CACHE_SIZE, Unused),
+        QVector<sample_t>(CACHE_SIZE, SAMPLE_MAX),
+        QVector<sample_t>(CACHE_SIZE, SAMPLE_MIN)
+    });
 
     // mark the new cache content as invalid
     invalidateCache(track_id, 0, CACHE_SIZE - 1);
@@ -209,11 +199,7 @@ void Kwave::OverViewCache::slotTrackInserted(quint64 track_id)
 void Kwave::OverViewCache::slotTrackDeleted(quint64 track_id)
 {
     QMutexLocker lock(&m_lock);
-
-    m_min.remove(track_id);
-    m_max.remove(track_id);
-    m_state.remove(track_id);
-
+    m_track_state.remove(track_id);
     emit changed();
 }
 
@@ -288,10 +274,8 @@ int Kwave::OverViewCache::getMinMax(int width, MinMaxArray &minmax)
         Kwave::SinglePassForward,
         m_signal, track_list, first, last
     );
-    Q_ASSERT(m_min.count() == m_max.count());
-    Q_ASSERT(m_min.count() == m_state.count());
 
-    if ((length / m_scale < 2) || src.isEmpty() || !m_state.count())
+    if ((length / m_scale < 2) || src.isEmpty() || !m_track_state.count())
         return 0; // empty ?
 
     // loop over all min/max buffers and make their content valid
@@ -302,14 +286,16 @@ int Kwave::OverViewCache::getMinMax(int width, MinMaxArray &minmax)
         quint64 uid = m_signal.uidOfTrack(track_list[index]);
         if (uid == 0) continue; // track has just been deleted
 
+        QHash<quint64, TrackState>::iterator it = m_track_state.find(uid);
+
         // check: maybe slotTrackInserted has not yet been called
         //        or slotTrackDeleted has just been called
-        if (!m_state.contains(uid))
+        if (it == m_track_state.end())
             continue;
 
-        sample_t *min = m_min[uid].data();
-        sample_t *max = m_max[uid].data();
-        CacheState *state = m_state[uid].data();
+        CacheState *state = (*it).m_state.data();
+        sample_t   *min   = (*it).m_min.data();
+        sample_t   *max   = (*it).m_max.data();
         Q_ASSERT(min && max && state);
         Kwave::SampleReader *reader = src[index];
         Q_ASSERT(reader);
@@ -346,15 +332,12 @@ int Kwave::OverViewCache::getMinMax(int width, MinMaxArray &minmax)
         sample_t maximum = SAMPLE_MIN;
         for (; index <= last_index; ++index) {
             // loop over all tracks
-            for (QHash<quint64, QVector <CacheState> >::const_iterator
-                 it(m_state.constBegin()); it != m_state.constEnd(); ++it)
-            {
-                const quint64 uid = it.key();
-                sample_t *min = m_min[uid].data();
-                sample_t *max = m_max[uid].data();
-                const CacheState *state = it.value().constData();
-                Q_ASSERT(state);
-                if (!state) continue;
+            for (const auto &it : m_track_state) {
+                const CacheState *state = it.m_state.constData();
+                const sample_t   *min   = it.m_min.constData();
+                const sample_t   *max   = it.m_max.constData();
+                Q_ASSERT(state && min && max);
+                if (!state || !min || !max) continue;
                 if (state[index] != Valid) {
                     if (minimum > 0) minimum = 0;
                     if (maximum < 0) maximum = 0;
diff --git a/libgui/OverViewCache.h b/libgui/OverViewCache.h
index a9619c97..5e70acd1 100644
--- a/libgui/OverViewCache.h
+++ b/libgui/OverViewCache.h
@@ -173,20 +173,27 @@ namespace Kwave
 
     private:
 
+        /** combined state/min/max */
+        struct TrackState
+        {
+            /** bitmask for "validity" of the min/max values */
+            QVector <CacheState> m_state;
+
+            /** list of minimum value arrays */
+            QVector<sample_t> m_min;
+
+            /** list of maximum value arrays */
+            QVector <sample_t> m_max;
+        };
+
         /** signal with the data to be shown */
         Kwave::SignalManager &m_signal;
 
         /** selection tracker */
         Kwave::SelectionTracker m_selection;
 
-        /** list of minimum value arrays, one array per track */
-        QHash<quint64, QVector <sample_t> > m_min;
-
-        /** list of maximum value arrays, one array per track */
-        QHash<quint64, QVector <sample_t> > m_max;
-
-        /** bitmask for "validity" of the min/max values */
-        QHash<quint64, QVector <CacheState> > m_state;
+        /** combined state/min/max, one per track */
+        QHash<quint64, TrackState> m_track_state;
 
         /** list of min/max pairs, cached internally for getOverView */
         MinMaxArray m_minmax;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.