changeset 1256:d8d6d01505ed 3.0-integration

Print out cache hit/miss counts
author Chris Cannam
date Wed, 09 Nov 2016 18:08:40 +0000
parents ca9032dd2811
children 5236543343c3
files base/HitCount.h data/fileio/WavFileReader.cpp data/model/FFTModel.cpp files.pri
diffstat 4 files changed, 94 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/HitCount.h	Wed Nov 09 18:08:40 2016 +0000
@@ -0,0 +1,68 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef HIT_COUNT_H
+#define HIT_COUNT_H
+
+#include <string>
+#include <iostream>
+
+/**
+ * Profile class for counting cache hits and the like.
+ */
+class HitCount
+{
+public:
+    HitCount(std::string name) :
+	m_name(name),
+	m_hit(0),
+	m_partial(0),
+	m_miss(0)
+    { }
+    
+    ~HitCount() {
+	using namespace std;
+	int total = m_hit + m_partial + m_miss;
+	cerr << "Hit count: " << m_name << ": ";
+	if (m_partial > 0) {
+	    cerr << m_hit << " hits, " << m_partial << " partial, "
+		 << m_miss << " misses";
+	} else {
+	    cerr << m_hit << " hits, " << m_miss << " misses";
+	}
+	if (total > 0) {
+	    if (m_partial > 0) {
+		cerr << " (" << ((m_hit * 100.0) / total) << "%, "
+		     << ((m_partial * 100.0) / total) << "%, "
+		     << ((m_miss * 100.0) / total) << "%)";
+	    } else {
+		cerr << " (" << ((m_hit * 100.0) / total) << "%, "
+		     << ((m_miss * 100.0) / total) << "%)";
+	    }
+	}
+	cerr << endl;
+    }
+
+    void hit() { ++m_hit; }
+    void partial() { ++m_partial; }
+    void miss() { ++m_miss; }
+
+private:
+    std::string m_name;
+    int m_hit;
+    int m_partial;
+    int m_miss;
+};
+
+#endif
--- a/data/fileio/WavFileReader.cpp	Sat Nov 05 10:41:41 2016 +0000
+++ b/data/fileio/WavFileReader.cpp	Wed Nov 09 18:08:40 2016 +0000
@@ -15,6 +15,8 @@
 
 #include "WavFileReader.h"
 
+#include "base/HitCount.h"
+
 #include <iostream>
 
 #include <QMutexLocker>
@@ -130,6 +132,8 @@
 vector<float>
 WavFileReader::getInterleavedFrames(sv_frame_t start, sv_frame_t count) const
 {
+    static HitCount lastRead("WavFileReader: last read");
+
     if (count == 0) return {};
 
     QMutexLocker locker(&m_mutex);
@@ -152,8 +156,18 @@
     // individual channels, it's quite common for us to be called
     // repeatedly for the same data. So this is worth cacheing.
     if (start == m_lastStart && count == m_lastCount) {
+        lastRead.hit();
         return m_buffer;
     }
+
+    // We don't actually support partial cache reads, but let's use
+    // the term partial to refer to any forward seek and consider a
+    // backward seek to be a miss
+    if (start >= m_lastStart) {
+        lastRead.partial();
+    } else {
+        lastRead.miss();
+    }
     
     if (sf_seek(m_file, start, SEEK_SET) < 0) {
         return {};
--- a/data/model/FFTModel.cpp	Sat Nov 05 10:41:41 2016 +0000
+++ b/data/model/FFTModel.cpp	Wed Nov 09 18:08:40 2016 +0000
@@ -18,6 +18,7 @@
 
 #include "base/Profiler.h"
 #include "base/Pitch.h"
+#include "base/HitCount.h"
 
 #include <algorithm>
 
@@ -26,6 +27,9 @@
 
 using namespace std;
 
+static HitCount inSmallCache("FFTModel: Small FFT cache");
+static HitCount inSourceCache("FFTModel: Source data cache");
+
 FFTModel::FFTModel(const DenseTimeValueModel *model,
                    int channel,
                    WindowType windowType,
@@ -215,6 +219,7 @@
 //         << "," << m_savedData.range.second << ")" << endl;
 
     if (m_savedData.range == range) {
+        inSourceCache.hit();
         return m_savedData.data;
     }
 
@@ -222,6 +227,8 @@
         range.first >= m_savedData.range.first &&
         range.second > m_savedData.range.second) {
 
+        inSourceCache.partial();
+        
         sv_frame_t discard = range.first - m_savedData.range.first;
 
         vector<float> acc(m_savedData.data.begin() + discard,
@@ -237,6 +244,8 @@
 
     } else {
 
+        inSourceCache.miss();
+        
         auto data = getSourceDataUncached(range);
         m_savedData = { range, data };
         return data;
@@ -284,9 +293,11 @@
 {
     for (auto &incache : m_cached) {
         if (incache.n == n) {
+            inSmallCache.hit();
             return incache.col;
         }
     }
+    inSmallCache.miss();
     
     auto samples = getSourceSamples(n);
     m_windower.cut(samples.data());
--- a/files.pri	Sat Nov 05 10:41:41 2016 +0000
+++ b/files.pri	Wed Nov 09 18:08:40 2016 +0000
@@ -8,6 +8,7 @@
            base/Debug.h \
            base/Exceptions.h \
            base/HelperExecPath.h \
+           base/HitCount.h \
            base/LogRange.h \
            base/MagnitudeRange.h \
            base/Pitch.h \