annotate base/StorageAdviser.cpp @ 335:02d2ad95ea52 spectrogram-cache-rejig

* Get storage advice for each cache in an FFT data server. Allows us to be more confident about the actual memory situation and cut over from memory to disc part way through an FFT calculation if necessary. StorageAdviser is now a bit too optimistic though (it's too keen to allocate large numbers of small blocks in memory).
author Chris Cannam
date Tue, 13 Nov 2007 13:54:10 +0000
parents aa8dbac62024
children 7cc6b7b0d819
rev   line source
Chris@168 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@168 2
Chris@168 3 /*
Chris@168 4 Sonic Visualiser
Chris@168 5 An audio file viewer and annotation editor.
Chris@168 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 QMUL.
Chris@168 8
Chris@168 9 This program is free software; you can redistribute it and/or
Chris@168 10 modify it under the terms of the GNU General Public License as
Chris@168 11 published by the Free Software Foundation; either version 2 of the
Chris@168 12 License, or (at your option) any later version. See the file
Chris@168 13 COPYING included with this distribution for more information.
Chris@168 14 */
Chris@168 15
Chris@168 16 #include "StorageAdviser.h"
Chris@168 17
Chris@168 18 #include "Exceptions.h"
Chris@168 19 #include "TempDirectory.h"
Chris@168 20
Chris@168 21 #include "system/System.h"
Chris@168 22
Chris@168 23 #include <iostream>
Chris@168 24
Chris@205 25 long StorageAdviser::m_discPlanned = 0;
Chris@205 26 long StorageAdviser::m_memoryPlanned = 0;
Chris@205 27
Chris@168 28 StorageAdviser::Recommendation
Chris@168 29 StorageAdviser::recommend(Criteria criteria,
Chris@168 30 int minimumSize,
Chris@168 31 int maximumSize)
Chris@168 32 {
Chris@170 33 std::cerr << "StorageAdviser::recommend: Criteria " << criteria
Chris@170 34 << ", minimumSize " << minimumSize
Chris@170 35 << ", maximumSize " << maximumSize << std::endl;
Chris@170 36
Chris@168 37 QString path = TempDirectory::getInstance()->getPath();
Chris@170 38 int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit());
Chris@170 39 int memoryFree, memoryTotal;
Chris@170 40 GetRealMemoryMBAvailable(memoryFree, memoryTotal);
Chris@168 41
Chris@205 42 if (discFree > m_discPlanned / 1024 + 1) {
Chris@205 43 discFree -= m_discPlanned / 1024 + 1;
Chris@205 44 } else if (discFree > 0) { // can also be -1 for unknown
Chris@205 45 discFree = 0;
Chris@205 46 }
Chris@205 47
Chris@205 48 if (memoryFree > m_memoryPlanned / 1024 + 1) {
Chris@205 49 memoryFree -= m_memoryPlanned / 1024 + 1;
Chris@205 50 } else if (memoryFree > 0) { // can also be -1 for unknown
Chris@205 51 memoryFree = 0;
Chris@205 52 }
Chris@205 53
Chris@334 54 std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << std::endl;
Chris@168 55
Chris@192 56 //!!! We have a potentially serious problem here if multiple
Chris@192 57 //recommendations are made in advance of any of the resulting
Chris@192 58 //allocations, as the allocations that have been recommended for
Chris@192 59 //won't be taken into account in subsequent recommendations.
Chris@192 60
Chris@170 61 enum StorageStatus {
Chris@170 62 Unknown,
Chris@170 63 Insufficient,
Chris@170 64 Marginal,
Chris@170 65 Sufficient
Chris@170 66 };
Chris@168 67
Chris@170 68 StorageStatus memoryStatus = Unknown;
Chris@170 69 StorageStatus discStatus = Unknown;
Chris@170 70
Chris@170 71 int minmb = minimumSize / 1024 + 1;
Chris@170 72 int maxmb = maximumSize / 1024 + 1;
Chris@170 73
Chris@170 74 if (memoryFree == -1) memoryStatus = Unknown;
Chris@170 75 else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient;
Chris@170 76 else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal;
Chris@170 77 else if (minmb > (memoryFree / 3)) memoryStatus = Marginal;
Chris@170 78 else if (memoryTotal == -1 ||
Chris@170 79 minmb > (memoryTotal / 10)) memoryStatus = Marginal;
Chris@335 80 else if (memoryFree < memoryTotal / 4) memoryStatus = Marginal;
Chris@170 81 else memoryStatus = Sufficient;
Chris@170 82
Chris@170 83 if (discFree == -1) discStatus = Unknown;
Chris@170 84 else if (minmb > (discFree * 3) / 4) discStatus = Insufficient;
Chris@173 85 else if (maxmb > (discFree / 4)) discStatus = Marginal;
Chris@173 86 else if (minmb > (discFree / 10)) discStatus = Marginal;
Chris@170 87 else discStatus = Sufficient;
Chris@170 88
Chris@170 89 std::cerr << "Memory status: " << memoryStatus << ", disc status "
Chris@170 90 << discStatus << std::endl;
Chris@170 91
Chris@170 92 int recommendation = NoRecommendation;
Chris@170 93
Chris@170 94 if (memoryStatus == Insufficient || memoryStatus == Unknown) {
Chris@170 95
Chris@170 96 recommendation |= UseDisc;
Chris@170 97
Chris@170 98 if (discStatus == Insufficient && minmb > discFree) {
Chris@170 99 throw InsufficientDiscSpace(path, minmb, discFree);
Chris@170 100 }
Chris@170 101
Chris@170 102 if (discStatus == Insufficient || discStatus == Marginal) {
Chris@170 103 recommendation |= ConserveSpace;
Chris@170 104 } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) {
Chris@170 105 recommendation |= ConserveSpace;
Chris@170 106 } else {
Chris@170 107 recommendation |= UseAsMuchAsYouLike;
Chris@170 108 }
Chris@170 109
Chris@170 110 } else if (memoryStatus == Marginal) {
Chris@170 111
Chris@170 112 if (((criteria & SpeedCritical) ||
Chris@170 113 (criteria & FrequentLookupLikely)) &&
Chris@170 114 !(criteria & PrecisionCritical) &&
Chris@170 115 !(criteria & LongRetentionLikely)) {
Chris@170 116
Chris@170 117 // requirements suggest a preference for memory
Chris@170 118
Chris@170 119 if (discStatus != Insufficient) {
Chris@170 120 recommendation |= PreferMemory;
Chris@170 121 } else {
Chris@170 122 recommendation |= UseMemory;
Chris@170 123 }
Chris@170 124
Chris@170 125 recommendation |= ConserveSpace;
Chris@170 126
Chris@170 127 } else {
Chris@170 128
Chris@170 129 if (discStatus == Insufficient) {
Chris@170 130 recommendation |= (UseMemory | ConserveSpace);
Chris@170 131 } else if (discStatus == Marginal) {
Chris@170 132 recommendation |= (PreferMemory | ConserveSpace);
Chris@170 133 } else if (discStatus == Unknown) {
Chris@170 134 recommendation |= (PreferDisc | ConserveSpace);
Chris@170 135 } else {
Chris@170 136 recommendation |= (UseDisc | UseAsMuchAsYouLike);
Chris@170 137 }
Chris@170 138 }
Chris@170 139
Chris@170 140 } else {
Chris@170 141
Chris@170 142 if (discStatus == Insufficient) {
Chris@170 143 recommendation |= (UseMemory | ConserveSpace);
Chris@170 144 } else if (discStatus != Sufficient) {
Chris@170 145 recommendation |= (PreferMemory | ConserveSpace);
Chris@170 146 } else {
Chris@170 147
Chris@170 148 if ((criteria & SpeedCritical) ||
Chris@170 149 (criteria & FrequentLookupLikely)) {
Chris@170 150 recommendation |= PreferMemory;
Chris@170 151 if (criteria & PrecisionCritical) {
Chris@170 152 recommendation |= UseAsMuchAsYouLike;
Chris@170 153 } else {
Chris@170 154 recommendation |= ConserveSpace;
Chris@170 155 }
Chris@170 156 } else {
Chris@170 157 recommendation |= PreferDisc;
Chris@170 158 recommendation |= UseAsMuchAsYouLike;
Chris@170 159 }
Chris@170 160 }
Chris@170 161 }
Chris@170 162
Chris@170 163 return Recommendation(recommendation);
Chris@168 164 }
Chris@168 165
Chris@205 166 void
Chris@205 167 StorageAdviser::notifyPlannedAllocation(AllocationArea area, int size)
Chris@205 168 {
Chris@205 169 if (area == MemoryAllocation) m_memoryPlanned += size;
Chris@205 170 else if (area == DiscAllocation) m_discPlanned += size;
Chris@259 171 // std::cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
Chris@259 172 // << m_discPlanned << std::endl;
Chris@205 173 }
Chris@205 174
Chris@205 175 void
Chris@205 176 StorageAdviser::notifyDoneAllocation(AllocationArea area, int size)
Chris@205 177 {
Chris@205 178 if (area == MemoryAllocation) {
Chris@205 179 if (m_memoryPlanned > size) m_memoryPlanned -= size;
Chris@205 180 else m_memoryPlanned = 0;
Chris@205 181 } else if (area == DiscAllocation) {
Chris@205 182 if (m_discPlanned > size) m_discPlanned -= size;
Chris@205 183 else m_discPlanned = 0;
Chris@205 184 }
Chris@259 185 // std::cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
Chris@259 186 // << m_discPlanned << std::endl;
Chris@205 187 }
Chris@205 188