#include "vtkExodusIICache.h" #include "vtkDataArray.h" #include "vtkObjectFactory.h" // Define VTK_EXO_DBG_CACHE to print cache adds, drops, and replacements. //#undef VTK_EXO_DBG_CACHE #define VTK_EXO_PRT_KEY(ckey) \ "(" << (ckey).Time << ", " << (ckey).ObjectType << ", " << (ckey).ObjectId << ", " \ << (ckey).ArrayId << ")" #define VTK_EXO_PRT_ARR(cval) \ " [" << (cval) << "," << ((cval) ? (cval)->GetActualMemorySize() / 1024. : 0.) << "/" \ << this->Size << "/" << this->Capacity << "]" #define VTK_EXO_PRT_ARR2(cval) \ " [" << (cval) << ", " << ((cval) ? (cval)->GetActualMemorySize() / 1024. : 0.) << "]" #if 0 static void printCache( vtkExodusIICacheSet& cache, vtkExodusIICacheLRU& lru ) { cout << "Cache\n"; vtkExodusIICacheRef cit; for ( cit = cache.begin(); cit != cache.end(); ++cit ) { cout << VTK_EXO_PRT_KEY( cit->first ) << VTK_EXO_PRT_ARR2( cit->second->GetValue() ) << "\n"; } cout << "LRU\n"; vtkExodusIICacheLRURef lit; for ( lit = lru.begin(); lit != lru.end(); ++lit ) { cout << VTK_EXO_PRT_KEY( (*lit)->first ) << "\n"; } } #endif // 0 // ============================================================================ vtkExodusIICacheEntry::vtkExodusIICacheEntry() { this->Value = nullptr; } vtkExodusIICacheEntry::vtkExodusIICacheEntry(vtkDataArray* arr) { this->Value = arr; if (arr) this->Value->Register(nullptr); } vtkExodusIICacheEntry::~vtkExodusIICacheEntry() { if (this->Value) this->Value->Delete(); } vtkExodusIICacheEntry::vtkExodusIICacheEntry(const vtkExodusIICacheEntry& other) { this->Value = other.Value; if (this->Value) this->Value->Register(nullptr); } #if 0 void printLRUBack( vtkExodusIICacheRef& cit ) { cout << "Key is " << VTK_EXO_PRT_KEY( cit->first ) << "\n"; } #endif // 0 // ============================================================================ vtkStandardNewMacro(vtkExodusIICache); vtkExodusIICache::vtkExodusIICache() { this->Size = 0.; this->Capacity = 2.; } vtkExodusIICache::~vtkExodusIICache() { this->ReduceToSize(0.); } void vtkExodusIICache::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Capacity: " << this->Capacity << " MiB\n"; os << indent << "Size: " << this->Size << " MiB\n"; os << indent << "Cache: " << &this->Cache << " (" << this->Cache.size() << ")\n"; os << indent << "LRU: " << &this->LRU << "\n"; } void vtkExodusIICache::Clear() { // printCache( this->Cache, this->LRU ); this->ReduceToSize(0.); } void vtkExodusIICache::SetCacheCapacity(double sizeInMiB) { if (sizeInMiB == this->Capacity) return; if (this->Size > sizeInMiB) { this->ReduceToSize(sizeInMiB); } this->Capacity = sizeInMiB < 0 ? 0 : sizeInMiB; } int vtkExodusIICache::ReduceToSize(double newSize) { int deletedSomething = 0; while (this->Size > newSize && !this->LRU.empty()) { vtkExodusIICacheRef cit(this->LRU.back()); vtkDataArray* arr = cit->second->Value; if (arr) { deletedSomething = 1; double arrSz = (double)arr->GetActualMemorySize() / 1024.; this->Size -= arrSz; #ifdef VTK_EXO_DBG_CACHE cout << "Dropping " << VTK_EXO_PRT_KEY(cit->first) << VTK_EXO_PRT_ARR(arr) << "\n"; #endif // VTK_EXO_DBG_CACHE if (this->Size <= 0) { if (this->Cache.empty()) this->Size = 0.; else this->RecomputeSize(); // oops, FP roundoff } } else { #ifdef VTK_EXO_DBG_CACHE cout << "Dropping " << VTK_EXO_PRT_KEY(cit->first) << VTK_EXO_PRT_ARR(arr) << "\n"; #endif // VTK_EXO_DBG_CACHE } delete cit->second; this->Cache.erase(cit); this->LRU.pop_back(); } if (this->Cache.empty()) { this->Size = 0; } return deletedSomething; } void vtkExodusIICache::Insert(vtkExodusIICacheKey& key, vtkDataArray* value) { double vsize = value ? value->GetActualMemorySize() / 1024. : 0.; vtkExodusIICacheRef it = this->Cache.find(key); if (it != this->Cache.end()) { if (it->second->Value == value) return; // Remove existing array and put in our new one. this->Size -= vsize; if (this->Size <= 0) { this->RecomputeSize(); } this->ReduceToSize(this->Capacity - vsize); it->second->Value->Delete(); it->second->Value = value; it->second->Value->Register( nullptr); // Since we re-use the cache entry, the constructor's Register won't get called. this->Size += vsize; #ifdef VTK_EXO_DBG_CACHE cout << "Replacing " << VTK_EXO_PRT_KEY(it->first) << VTK_EXO_PRT_ARR(value) << "\n"; #endif // VTK_EXO_DBG_CACHE this->LRU.erase(it->second->LRUEntry); it->second->LRUEntry = this->LRU.insert(this->LRU.begin(), it); } else { this->ReduceToSize(this->Capacity - vsize); std::pair entry( key, new vtkExodusIICacheEntry(value)); std::pair iret = this->Cache.insert(entry); this->Size += vsize; #ifdef VTK_EXO_DBG_CACHE cout << "Adding " << VTK_EXO_PRT_KEY(key) << VTK_EXO_PRT_ARR(value) << "\n"; #endif // VTK_EXO_DBG_CACHE iret.first->second->LRUEntry = this->LRU.insert(this->LRU.begin(), iret.first); } // printCache( this->Cache, this->LRU ); } vtkDataArray*& vtkExodusIICache::Find(const vtkExodusIICacheKey& key) { static vtkDataArray* dummy = nullptr; vtkExodusIICacheRef it = this->Cache.find(key); if (it != this->Cache.end()) { this->LRU.erase(it->second->LRUEntry); it->second->LRUEntry = this->LRU.insert(this->LRU.begin(), it); return it->second->Value; } dummy = nullptr; return dummy; } int vtkExodusIICache::Invalidate(const vtkExodusIICacheKey& key) { vtkExodusIICacheRef it = this->Cache.find(key); if (it != this->Cache.end()) { #ifdef VTK_EXO_DBG_CACHE cout << "Dropping " << VTK_EXO_PRT_KEY(it->first) << VTK_EXO_PRT_ARR(it->second->Value) << "\n"; #endif // VTK_EXO_DBG_CACHE this->LRU.erase(it->second->LRUEntry); if (it->second->Value) { this->Size -= it->second->Value->GetActualMemorySize() / 1024.; } delete it->second; this->Cache.erase(it); if (this->Size <= 0) { if (this->Cache.empty()) this->Size = 0.; else this->RecomputeSize(); // oops, FP roundoff } return 1; } return 0; } int vtkExodusIICache::Invalidate(const vtkExodusIICacheKey& key, const vtkExodusIICacheKey& pattern) { vtkExodusIICacheRef it; int nDropped = 0; it = this->Cache.begin(); while (it != this->Cache.end()) { if (!it->first.match(key, pattern)) { ++it; continue; } #ifdef VTK_EXO_DBG_CACHE cout << "Dropping " << VTK_EXO_PRT_KEY(it->first) << VTK_EXO_PRT_ARR(it->second->Value) << "\n"; #endif // VTK_EXO_DBG_CACHE this->LRU.erase(it->second->LRUEntry); if (it->second->Value) { this->Size -= it->second->Value->GetActualMemorySize() / 1024.; } vtkExodusIICacheRef tmpIt = it++; delete tmpIt->second; this->Cache.erase(tmpIt); if (this->Size <= 0) { if (this->Cache.empty()) this->Size = 0.; else this->RecomputeSize(); // oops, FP roundoff } ++nDropped; } return nDropped; } void vtkExodusIICache::RecomputeSize() { this->Size = 0.; vtkExodusIICacheRef it; for (it = this->Cache.begin(); it != this->Cache.end(); ++it) { if (it->second->Value) { this->Size += (double)it->second->Value->GetActualMemorySize() / 1024.; } } }