1 #include "vtkExodusIICache.h"
2 
3 #include "vtkDataArray.h"
4 #include "vtkObjectFactory.h"
5 
6 // Define VTK_EXO_DBG_CACHE to print cache adds, drops, and replacements.
7 //#undef VTK_EXO_DBG_CACHE
8 
9 #define VTK_EXO_PRT_KEY(ckey)                                                                      \
10   "(" << (ckey).Time << ", " << (ckey).ObjectType << ", " << (ckey).ObjectId << ", "               \
11       << (ckey).ArrayId << ")"
12 #define VTK_EXO_PRT_ARR(cval)                                                                      \
13   " [" << (cval) << "," << ((cval) ? (cval)->GetActualMemorySize() / 1024. : 0.) << "/"            \
14        << this->Size << "/" << this->Capacity << "]"
15 #define VTK_EXO_PRT_ARR2(cval)                                                                     \
16   " [" << (cval) << ", " << ((cval) ? (cval)->GetActualMemorySize() / 1024. : 0.) << "]"
17 
18 #if 0
19 static void printCache( vtkExodusIICacheSet& cache, vtkExodusIICacheLRU& lru )
20 {
21   cout << "Cache\n";
22   vtkExodusIICacheRef cit;
23   for ( cit = cache.begin(); cit != cache.end(); ++cit )
24   {
25     cout << VTK_EXO_PRT_KEY( cit->first ) << VTK_EXO_PRT_ARR2( cit->second->GetValue() ) << "\n";
26   }
27   cout << "LRU\n";
28   vtkExodusIICacheLRURef lit;
29   for ( lit = lru.begin(); lit != lru.end(); ++lit )
30   {
31     cout << VTK_EXO_PRT_KEY( (*lit)->first ) << "\n";
32   }
33 }
34 #endif // 0
35 
36 // ============================================================================
vtkExodusIICacheEntry()37 vtkExodusIICacheEntry::vtkExodusIICacheEntry()
38 {
39   this->Value = nullptr;
40 }
41 
vtkExodusIICacheEntry(vtkDataArray * arr)42 vtkExodusIICacheEntry::vtkExodusIICacheEntry(vtkDataArray* arr)
43 {
44   this->Value = arr;
45   if (arr)
46     this->Value->Register(nullptr);
47 }
~vtkExodusIICacheEntry()48 vtkExodusIICacheEntry::~vtkExodusIICacheEntry()
49 {
50   if (this->Value)
51     this->Value->Delete();
52 }
53 
vtkExodusIICacheEntry(const vtkExodusIICacheEntry & other)54 vtkExodusIICacheEntry::vtkExodusIICacheEntry(const vtkExodusIICacheEntry& other)
55 {
56   this->Value = other.Value;
57   if (this->Value)
58     this->Value->Register(nullptr);
59 }
60 
61 #if 0
62 void printLRUBack( vtkExodusIICacheRef& cit )
63 {
64   cout << "Key is " << VTK_EXO_PRT_KEY( cit->first ) << "\n";
65 }
66 #endif // 0
67 
68 // ============================================================================
69 
70 vtkStandardNewMacro(vtkExodusIICache);
71 
vtkExodusIICache()72 vtkExodusIICache::vtkExodusIICache()
73 {
74   this->Size = 0.;
75   this->Capacity = 2.;
76 }
77 
~vtkExodusIICache()78 vtkExodusIICache::~vtkExodusIICache()
79 {
80   this->ReduceToSize(0.);
81 }
82 
PrintSelf(ostream & os,vtkIndent indent)83 void vtkExodusIICache::PrintSelf(ostream& os, vtkIndent indent)
84 {
85   this->Superclass::PrintSelf(os, indent);
86   os << indent << "Capacity: " << this->Capacity << " MiB\n";
87   os << indent << "Size: " << this->Size << " MiB\n";
88   os << indent << "Cache: " << &this->Cache << " (" << this->Cache.size() << ")\n";
89   os << indent << "LRU: " << &this->LRU << "\n";
90 }
91 
Clear()92 void vtkExodusIICache::Clear()
93 {
94   // printCache( this->Cache, this->LRU );
95   this->ReduceToSize(0.);
96 }
97 
SetCacheCapacity(double sizeInMiB)98 void vtkExodusIICache::SetCacheCapacity(double sizeInMiB)
99 {
100   if (sizeInMiB == this->Capacity)
101     return;
102 
103   if (this->Size > sizeInMiB)
104   {
105     this->ReduceToSize(sizeInMiB);
106   }
107 
108   this->Capacity = sizeInMiB < 0 ? 0 : sizeInMiB;
109 }
110 
ReduceToSize(double newSize)111 int vtkExodusIICache::ReduceToSize(double newSize)
112 {
113   int deletedSomething = 0;
114   while (this->Size > newSize && !this->LRU.empty())
115   {
116     vtkExodusIICacheRef cit(this->LRU.back());
117     vtkDataArray* arr = cit->second->Value;
118     if (arr)
119     {
120       deletedSomething = 1;
121       double arrSz = (double)arr->GetActualMemorySize() / 1024.;
122       this->Size -= arrSz;
123 #ifdef VTK_EXO_DBG_CACHE
124       cout << "Dropping " << VTK_EXO_PRT_KEY(cit->first) << VTK_EXO_PRT_ARR(arr) << "\n";
125 #endif // VTK_EXO_DBG_CACHE
126       if (this->Size <= 0)
127       {
128         if (this->Cache.empty())
129           this->Size = 0.;
130         else
131           this->RecomputeSize(); // oops, FP roundoff
132       }
133     }
134     else
135     {
136 #ifdef VTK_EXO_DBG_CACHE
137       cout << "Dropping " << VTK_EXO_PRT_KEY(cit->first) << VTK_EXO_PRT_ARR(arr) << "\n";
138 #endif // VTK_EXO_DBG_CACHE
139     }
140 
141     delete cit->second;
142     this->Cache.erase(cit);
143     this->LRU.pop_back();
144   }
145 
146   if (this->Cache.empty())
147   {
148     this->Size = 0;
149   }
150 
151   return deletedSomething;
152 }
153 
Insert(vtkExodusIICacheKey & key,vtkDataArray * value)154 void vtkExodusIICache::Insert(vtkExodusIICacheKey& key, vtkDataArray* value)
155 {
156   double vsize = value ? value->GetActualMemorySize() / 1024. : 0.;
157 
158   vtkExodusIICacheRef it = this->Cache.find(key);
159   if (it != this->Cache.end())
160   {
161     if (it->second->Value == value)
162       return;
163 
164     // Remove existing array and put in our new one.
165     this->Size -= vsize;
166     if (this->Size <= 0)
167     {
168       this->RecomputeSize();
169     }
170     this->ReduceToSize(this->Capacity - vsize);
171     it->second->Value->Delete();
172     it->second->Value = value;
173     it->second->Value->Register(
174       nullptr); // Since we re-use the cache entry, the constructor's Register won't get called.
175     this->Size += vsize;
176 #ifdef VTK_EXO_DBG_CACHE
177     cout << "Replacing " << VTK_EXO_PRT_KEY(it->first) << VTK_EXO_PRT_ARR(value) << "\n";
178 #endif // VTK_EXO_DBG_CACHE
179     this->LRU.erase(it->second->LRUEntry);
180     it->second->LRUEntry = this->LRU.insert(this->LRU.begin(), it);
181   }
182   else
183   {
184     this->ReduceToSize(this->Capacity - vsize);
185     std::pair<const vtkExodusIICacheKey, vtkExodusIICacheEntry*> entry(
186       key, new vtkExodusIICacheEntry(value));
187     std::pair<vtkExodusIICacheSet::iterator, bool> iret = this->Cache.insert(entry);
188     this->Size += vsize;
189 #ifdef VTK_EXO_DBG_CACHE
190     cout << "Adding " << VTK_EXO_PRT_KEY(key) << VTK_EXO_PRT_ARR(value) << "\n";
191 #endif // VTK_EXO_DBG_CACHE
192     iret.first->second->LRUEntry = this->LRU.insert(this->LRU.begin(), iret.first);
193   }
194   // printCache( this->Cache, this->LRU );
195 }
196 
Find(const vtkExodusIICacheKey & key)197 vtkDataArray*& vtkExodusIICache::Find(const vtkExodusIICacheKey& key)
198 {
199   static vtkDataArray* dummy = nullptr;
200 
201   vtkExodusIICacheRef it = this->Cache.find(key);
202   if (it != this->Cache.end())
203   {
204     this->LRU.erase(it->second->LRUEntry);
205     it->second->LRUEntry = this->LRU.insert(this->LRU.begin(), it);
206     return it->second->Value;
207   }
208 
209   dummy = nullptr;
210   return dummy;
211 }
212 
Invalidate(const vtkExodusIICacheKey & key)213 int vtkExodusIICache::Invalidate(const vtkExodusIICacheKey& key)
214 {
215   vtkExodusIICacheRef it = this->Cache.find(key);
216   if (it != this->Cache.end())
217   {
218 #ifdef VTK_EXO_DBG_CACHE
219     cout << "Dropping " << VTK_EXO_PRT_KEY(it->first) << VTK_EXO_PRT_ARR(it->second->Value) << "\n";
220 #endif // VTK_EXO_DBG_CACHE
221     this->LRU.erase(it->second->LRUEntry);
222     if (it->second->Value)
223     {
224       this->Size -= it->second->Value->GetActualMemorySize() / 1024.;
225     }
226     delete it->second;
227     this->Cache.erase(it);
228 
229     if (this->Size <= 0)
230     {
231       if (this->Cache.empty())
232         this->Size = 0.;
233       else
234         this->RecomputeSize(); // oops, FP roundoff
235     }
236 
237     return 1;
238   }
239   return 0;
240 }
241 
Invalidate(const vtkExodusIICacheKey & key,const vtkExodusIICacheKey & pattern)242 int vtkExodusIICache::Invalidate(const vtkExodusIICacheKey& key, const vtkExodusIICacheKey& pattern)
243 {
244   vtkExodusIICacheRef it;
245   int nDropped = 0;
246   it = this->Cache.begin();
247   while (it != this->Cache.end())
248   {
249     if (!it->first.match(key, pattern))
250     {
251       ++it;
252       continue;
253     }
254 
255 #ifdef VTK_EXO_DBG_CACHE
256     cout << "Dropping " << VTK_EXO_PRT_KEY(it->first) << VTK_EXO_PRT_ARR(it->second->Value) << "\n";
257 #endif // VTK_EXO_DBG_CACHE
258     this->LRU.erase(it->second->LRUEntry);
259     if (it->second->Value)
260     {
261       this->Size -= it->second->Value->GetActualMemorySize() / 1024.;
262     }
263     vtkExodusIICacheRef tmpIt = it++;
264     delete tmpIt->second;
265     this->Cache.erase(tmpIt);
266 
267     if (this->Size <= 0)
268     {
269       if (this->Cache.empty())
270         this->Size = 0.;
271       else
272         this->RecomputeSize(); // oops, FP roundoff
273     }
274 
275     ++nDropped;
276   }
277   return nDropped;
278 }
279 
RecomputeSize()280 void vtkExodusIICache::RecomputeSize()
281 {
282   this->Size = 0.;
283   vtkExodusIICacheRef it;
284   for (it = this->Cache.begin(); it != this->Cache.end(); ++it)
285   {
286     if (it->second->Value)
287     {
288       this->Size += (double)it->second->Value->GetActualMemorySize() / 1024.;
289     }
290   }
291 }
292