Mercurial > hg > svcore
changeset 170:b23eea68357e
* flesh out StorageAdviser
author | Chris Cannam |
---|---|
date | Tue, 26 Sep 2006 12:58:12 +0000 |
parents | 603991c63ff6 |
children | ebf55cf0d34d |
files | base/StorageAdviser.cpp base/StorageAdviser.h base/TempDirectory.cpp data/fft/FFTDataServer.cpp data/fft/FFTFileCache.cpp data/fft/FFTFileCache.h data/fft/FFTMemoryCache.cpp data/fft/FFTMemoryCache.h system/System.cpp system/System.h |
diffstat | 10 files changed, 197 insertions(+), 41 deletions(-) [+] |
line wrap: on
line diff
--- a/base/StorageAdviser.cpp Mon Sep 25 20:32:44 2006 +0000 +++ b/base/StorageAdviser.cpp Tue Sep 26 12:58:12 2006 +0000 @@ -27,15 +27,118 @@ int minimumSize, int maximumSize) { + std::cerr << "StorageAdviser::recommend: Criteria " << criteria + << ", minimumSize " << minimumSize + << ", maximumSize " << maximumSize << std::endl; + QString path = TempDirectory::getInstance()->getPath(); + int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit()); + int memoryFree, memoryTotal; + GetRealMemoryMBAvailable(memoryFree, memoryTotal); - int discSpace = GetDiscSpaceMBAvailable(path.toLocal8Bit()); - int memory = GetRealMemoryMBAvailable(); + std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << std::endl; - std::cerr << "Disc space: " << discSpace << ", memory: " << memory << std::endl; + enum StorageStatus { + Unknown, + Insufficient, + Marginal, + Sufficient + }; - return Recommendation(0); + StorageStatus memoryStatus = Unknown; + StorageStatus discStatus = Unknown; + + int minmb = minimumSize / 1024 + 1; + int maxmb = maximumSize / 1024 + 1; + + if (memoryFree == -1) memoryStatus = Unknown; + else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient; + else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal; + else if (minmb > (memoryFree / 3)) memoryStatus = Marginal; + else if (memoryTotal == -1 || + minmb > (memoryTotal / 10)) memoryStatus = Marginal; + else memoryStatus = Sufficient; + + if (discFree == -1) discStatus = Unknown; + else if (minmb > (discFree * 3) / 4) discStatus = Insufficient; + else if (maxmb > (discFree * 3) / 4) discStatus = Marginal; + else if (minmb > (discFree / 3)) discStatus = Marginal; + else discStatus = Sufficient; + + std::cerr << "Memory status: " << memoryStatus << ", disc status " + << discStatus << std::endl; + + int recommendation = NoRecommendation; + + if (memoryStatus == Insufficient || memoryStatus == Unknown) { + + recommendation |= UseDisc; + + if (discStatus == Insufficient && minmb > discFree) { + throw InsufficientDiscSpace(path, minmb, discFree); + } + + if (discStatus == Insufficient || discStatus == Marginal) { + recommendation |= ConserveSpace; + } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) { + recommendation |= ConserveSpace; + } else { + recommendation |= UseAsMuchAsYouLike; + } + + } else if (memoryStatus == Marginal) { + + if (((criteria & SpeedCritical) || + (criteria & FrequentLookupLikely)) && + !(criteria & PrecisionCritical) && + !(criteria & LongRetentionLikely)) { + + // requirements suggest a preference for memory + + if (discStatus != Insufficient) { + recommendation |= PreferMemory; + } else { + recommendation |= UseMemory; + } + + recommendation |= ConserveSpace; + + } else { + + if (discStatus == Insufficient) { + recommendation |= (UseMemory | ConserveSpace); + } else if (discStatus == Marginal) { + recommendation |= (PreferMemory | ConserveSpace); + } else if (discStatus == Unknown) { + recommendation |= (PreferDisc | ConserveSpace); + } else { + recommendation |= (UseDisc | UseAsMuchAsYouLike); + } + } + + } else { + + if (discStatus == Insufficient) { + recommendation |= (UseMemory | ConserveSpace); + } else if (discStatus != Sufficient) { + recommendation |= (PreferMemory | ConserveSpace); + } else { + + if ((criteria & SpeedCritical) || + (criteria & FrequentLookupLikely)) { + recommendation |= PreferMemory; + if (criteria & PrecisionCritical) { + recommendation |= UseAsMuchAsYouLike; + } else { + recommendation |= ConserveSpace; + } + } else { + recommendation |= PreferDisc; + recommendation |= UseAsMuchAsYouLike; + } + } + } + + return Recommendation(recommendation); } - -
--- a/base/StorageAdviser.h Mon Sep 25 20:32:44 2006 +0000 +++ b/base/StorageAdviser.h Tue Sep 26 12:58:12 2006 +0000 @@ -19,6 +19,7 @@ /** * A utility class designed to help decide whether to store cache data * (for example FFT outputs) in memory or on disk in the TempDirectory. + * This is basically a compendium of simple rules of thumb. */ class StorageAdviser @@ -26,29 +27,33 @@ public: // pass to recommend() zero or more of these OR'd together enum Criteria { - SpeedCritical = 1, - PrecisionCritical = 2, - RepeatabilityUseful = 4 + NoCriteria = 0, + SpeedCritical = 1, + PrecisionCritical = 2, + LongRetentionLikely = 4, + FrequentLookupLikely = 8 }; // recommend() returns one or two of these OR'd together enum Recommendation { - UseMemory = 1, - UseDisc = 2, - ConserveSpace = 4, - UseAsMuchAsYouLike = 8 + NoRecommendation = 0, + UseMemory = 1, // Disc is strongly contraindicated + PreferMemory = 2, // Either would do; memory probably better + PreferDisc = 4, // Either would do; disc probably better + UseDisc = 8, // Probably won't fit in memory + ConserveSpace = 16,// Whatever you choose, keep it compact + UseAsMuchAsYouLike = 32 // Take my advice and there'll be space for all }; - // May throw InsufficientDiscSpace exception if it looks like - // minimumSize won't fit on the disc. - /** * Recommend where to store some data, given certain storage and * recall criteria. The minimum size is the approximate amount of - * data in bytes that will be stored if the recommendation is to - * ConserveSpace; the maximum size is approximately the amount + * data in kilobytes that will be stored if the recommendation is + * to ConserveSpace; the maximum size is approximately the amount * that will be used if UseAsMuchAsYouLike is returned. - **!!! sizes should be longer types + * + * May throw InsufficientDiscSpace exception if there appears to + * be nowhere the minimum amount of data can be stored. */ static Recommendation recommend(Criteria criteria, int minimumSize,
--- a/base/TempDirectory.cpp Mon Sep 25 20:32:44 2006 +0000 +++ b/base/TempDirectory.cpp Tue Sep 26 12:58:12 2006 +0000 @@ -20,6 +20,7 @@ #include <QDir> #include <QFile> #include <QMutexLocker> +#include <QSettings> #include <iostream> #include <cassert> @@ -58,16 +59,23 @@ if (m_tmpdir != "") return m_tmpdir; + QSettings settings; + settings.beginGroup("TempDirectory"); + QString svDirParent = settings.value("create-in", "$HOME").toString(); + settings.endGroup(); + + svDirParent.replace("$HOME", QDir::home().absolutePath()); + QString svDirBase = ".sv1"; - QString svDir = QDir::home().filePath(svDirBase); + QString svDir = QDir(svDirParent).filePath(svDirBase); if (!QFileInfo(svDir).exists()) { - if (!QDir::home().mkdir(svDirBase)) { - throw DirectoryCreationFailed(QString("%1 directory in $HOME") - .arg(svDirBase)); + if (!QDir(svDirParent).mkdir(svDirBase)) { + throw DirectoryCreationFailed(QString("%1 directory in %2") + .arg(svDirBase).arg(svDirParent)); } } else if (!QFileInfo(svDir).isDir()) { - throw DirectoryCreationFailed(QString("$HOME/%1 is not a directory") - .arg(svDirBase)); + throw DirectoryCreationFailed(QString("%1/%2 is not a directory") + .arg(svDirParent).arg(svDirBase)); } cleanupAbandonedDirectories(svDir);
--- a/data/fft/FFTDataServer.cpp Mon Sep 25 20:32:44 2006 +0000 +++ b/data/fft/FFTDataServer.cpp Tue Sep 26 12:58:12 2006 +0000 @@ -75,12 +75,19 @@ return server; } + StorageAdviser::Criteria criteria = + StorageAdviser::Criteria + (StorageAdviser::SpeedCritical | StorageAdviser::LongRetentionLikely); - //!!! + int cells = fftSize * ((model->getEndFrame() - model->getStartFrame()) + / windowIncrement + 1); + int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb + int maximumSize = (cells / 1024) * sizeof(float); // kb + + StorageAdviser::Recommendation recommendation = + StorageAdviser::recommend(criteria, minimumSize, maximumSize); - StorageAdviser::Recommendation recommendation = - StorageAdviser::recommend(StorageAdviser::Criteria(0), 0, 0); - + std::cerr << "Recommendation was: " << recommendation << std::endl; m_servers[n] = ServerCountPair (new FFTDataServer(n,
--- a/data/fft/FFTFileCache.cpp Mon Sep 25 20:32:44 2006 +0000 +++ b/data/fft/FFTFileCache.cpp Tue Sep 26 12:58:12 2006 +0000 @@ -286,3 +286,11 @@ m_mfc->setColumnAt(x, m_writebuf); } +size_t +FFTFileCache::getCacheSize(size_t width, size_t height, StorageType type) +{ + return (height * 2 + 1) * width * + (type == Compact ? sizeof(uint16_t) : sizeof(float)) + + 2 * sizeof(size_t); // matrix file header size +} +
--- a/data/fft/FFTFileCache.h Mon Sep 25 20:32:44 2006 +0000 +++ b/data/fft/FFTFileCache.h Tue Sep 26 12:58:12 2006 +0000 @@ -56,6 +56,8 @@ virtual void suspend() { m_mfc->suspend(); } + static size_t getCacheSize(size_t width, size_t height, StorageType type); + protected: char *m_writebuf; mutable char *m_readbuf;
--- a/data/fft/FFTMemoryCache.cpp Mon Sep 25 20:32:44 2006 +0000 +++ b/data/fft/FFTMemoryCache.cpp Tue Sep 26 12:58:12 2006 +0000 @@ -113,3 +113,9 @@ setColumnAt(x, reals, imags, max); } +size_t +FFTMemoryCache::getCacheSize(size_t width, size_t height) +{ + return (height * 2 + 1) * width * sizeof(uint16_t); +} +
--- a/data/fft/FFTMemoryCache.h Mon Sep 25 20:32:44 2006 +0000 +++ b/data/fft/FFTMemoryCache.h Tue Sep 26 12:58:12 2006 +0000 @@ -112,6 +112,8 @@ virtual void setColumnAt(size_t x, float *reals, float *imags); + static size_t getCacheSize(size_t width, size_t height); + private: size_t m_width; size_t m_height;
--- a/system/System.cpp Mon Sep 25 20:32:44 2006 +0000 +++ b/system/System.cpp Tue Sep 26 12:58:12 2006 +0000 @@ -18,6 +18,8 @@ #include <QStringList> #include <QString> +#include <stdint.h> + #ifndef _WIN32 #include <signal.h> #include <sys/statvfs.h> @@ -74,17 +76,21 @@ #endif } -int -GetRealMemoryMBAvailable() +void +GetRealMemoryMBAvailable(int &available, int &total) { + available = -1; + total = -1; + FILE *meminfo = fopen("/proc/meminfo", "r"); - if (!meminfo) return -1; + if (!meminfo) return; char buf[256]; while (!feof(meminfo)) { fgets(buf, 256, meminfo); - if (strncmp(buf, "MemFree:", 8)) { - fclose(meminfo); + bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0); + bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0)); + if (isMemFree || isMemTotal) { QString line = QString(buf).trimmed(); QStringList elements = line.split(' ', QString::SkipEmptyParts); QString unit = "kB"; @@ -92,14 +98,20 @@ int size = elements[1].toInt(); // std::cerr << "have size \"" << size << "\", unit \"" // << unit.toStdString() << "\"" << std::endl; - if (unit.toLower() == "gb") return size * 1024; - if (unit.toLower() == "mb") return size; - if (unit.toLower() == "kb") return size / 1024; - return size / 1048576; + if (unit.toLower() == "gb") size = size * 1024; + else if (unit.toLower() == "mb") size = size; + else if (unit.toLower() == "kb") size = size / 1024; + else size = size / 1048576; + + if (isMemFree) available = size; + else total = size; + } + if (available != -1 && total != -1) { + fclose(meminfo); + return; } } fclose(meminfo); - return -1; } int @@ -109,6 +121,7 @@ __int64 available, total, totalFree; if (GetDiskFreeSpaceEx(path, &available, &total, &totalFree)) { available /= 1048576; + if (available > INT_MAX) available = INT_MAX; return int(available); } else { std::cerr << "WARNING: GetDiskFreeSpaceEx failed: error code " @@ -121,7 +134,9 @@ // do the multiplies and divides in this order to reduce the // likelihood of arithmetic overflow std::cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << std::endl; - return ((buf.f_bavail / 1024) * buf.f_bsize) / 1024; + uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024; + if (available > INT_MAX) available = INT_MAX; + return int(available); } else { perror("statvfs failed"); return -1;
--- a/system/System.h Mon Sep 25 20:32:44 2006 +0000 +++ b/system/System.h Tue Sep 26 12:58:12 2006 +0000 @@ -77,7 +77,7 @@ // Return a vague approximation to the number of free megabytes of real memory. // Return -1 if unknown. -extern int GetRealMemoryMBAvailable(); +extern void GetRealMemoryMBAvailable(int &available, int &total); // Return a vague approximation to the number of free megabytes of disc space // on the partition containing the given path. Return -1 if unknown.