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