Panda3D
 All Classes Functions Variables Enumerations
adaptiveLru.cxx
1 // Filename: adaptiveLru.cxx
2 // Created by: drose (03Sep08)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "adaptiveLru.h"
16 #include "config_gobj.h"
17 #include "clockObject.h"
18 #include "indent.h"
19 
20 static const int HIGH_PRIORITY_SCALE = 4;
21 static const int LOW_PRIORITY_RANGE = 25;
22 
23 ////////////////////////////////////////////////////////////////////
24 // Function: AdaptiveLru::Constructor
25 // Access: Published
26 // Description:
27 ////////////////////////////////////////////////////////////////////
28 AdaptiveLru::
29 AdaptiveLru(const string &name, size_t max_size) :
30  Namable(name)
31 {
32  _total_size = 0;
33  _max_size = max_size;
34 
35  _current_frame_identifier = 0;
36  _weight = adaptive_lru_weight;
37  _max_updates_per_frame = adaptive_lru_max_updates_per_frame;
38 
39  // Initialize our list heads to empty.
40  _static_list._next = &_static_list;
41  _static_list._prev = &_static_list;
42 
43  int index;
44  for (index = 0; index < LPP_TotalPriorities; ++index) {
45  _page_array[index]._next = &_page_array[index];
46  _page_array[index]._prev = &_page_array[index];
47  }
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: AdaptiveLru::Destructor
52 // Access: Published, Virtual
53 // Description:
54 ////////////////////////////////////////////////////////////////////
55 AdaptiveLru::
56 ~AdaptiveLru() {
57 #ifndef NDEBUG
58  // We're shutting down. Force-remove everything remaining, but
59  // don't explicitly evict it (that would force vertex buffers to
60  // write themselves to disk unnecessarily).
61 
62  while (_static_list._next != &_static_list) {
63  nassertv(_static_list._next != (LinkedListNode *)NULL);
64  AdaptiveLruPage *page = (AdaptiveLruPage *)(AdaptiveLruPageStaticList *)_static_list._next;
65 
66  page->_lru = NULL;
67  ((AdaptiveLruPageDynamicList *)page)->remove_from_list();
68  ((AdaptiveLruPageStaticList *)page)->remove_from_list();
69  }
70 #endif
71 }
72 
73 ////////////////////////////////////////////////////////////////////
74 // Function: AdaptiveLru::do_partial_lru_update
75 // Access: Private
76 // Description: This only updates a number of pages up to the
77 // specified maximum_updates. Assumes the lock is held.
78 ////////////////////////////////////////////////////////////////////
79 void AdaptiveLru::
80 do_partial_lru_update(int num_updates) {
81  // Iterate sequentially through the static list of pages. As we
82  // process each page, pop it and push it back on the tail. Stop
83  // when we have processed num_updates, or come back to the starting
84  // one.
85 
86  AdaptiveLruPageStaticList *start_node = (AdaptiveLruPageStaticList *)_static_list._next;
87  if (start_node == &_static_list) {
88  // List is empty.
89  return;
90  }
91 
92  AdaptiveLruPageStaticList *node = start_node;
93  do {
95  if (--num_updates <= 0) {
96  return;
97  }
98 
100  node->remove_from_list();
101  node->insert_before(&_static_list);
102  node = next;
103  } while (node != start_node && node != &_static_list);
104 }
105 
106 ////////////////////////////////////////////////////////////////////
107 // Function: AdaptiveLru::update_page
108 // Access: Private
109 // Description: This updates the page's average utilization.
110 // Priority LPP_New is considered to be average usage
111 // of 1.0 (which means the page is used once per frame
112 // on average). Priorities < LPP_New are for pages
113 // used more than once per frame and Priorities >
114 // LPP_New are for pages used less than once per frame.
115 //
116 // Assumes the lock is held.
117 ////////////////////////////////////////////////////////////////////
118 void AdaptiveLru::
120  int target_priority = page->_priority;
121  unsigned int lifetime_frames = _current_frame_identifier - page->_first_frame_identifier;
122  if (lifetime_frames > 0) {
123  if (page->_update_frame_identifier) {
124  unsigned int update_frames;
125 
126  update_frames = (_current_frame_identifier - page->_update_frame_identifier);
127  if (update_frames > 0) {
128  PN_stdfloat update_average_frame_utilization =
129  (PN_stdfloat) (page->_update_total_usage) / (PN_stdfloat)update_frames;
130 
131  page->_average_frame_utilization =
132  calculate_exponential_moving_average(update_average_frame_utilization,
133  page->_average_frame_utilization);
134 
135  target_priority = page->_priority;
136  if (page->_average_frame_utilization >= 1.0f) {
137  int integer_average_frame_utilization;
138 
139  integer_average_frame_utilization =
140  (int) ((page->_average_frame_utilization - 1.0f) *
141  (PN_stdfloat) HIGH_PRIORITY_SCALE);
142  if (integer_average_frame_utilization >= LPP_New) {
143  integer_average_frame_utilization = LPP_New;
144  }
145  integer_average_frame_utilization = LPP_New -
146  integer_average_frame_utilization;
147  target_priority = integer_average_frame_utilization;
148  } else {
149  int integer_average_frame_utilization;
150 
151  integer_average_frame_utilization = (int)
152  (page->_average_frame_utilization *
153  (PN_stdfloat) LOW_PRIORITY_RANGE);
154  integer_average_frame_utilization = LOW_PRIORITY_RANGE -
155  integer_average_frame_utilization;
156  target_priority = LPP_New + integer_average_frame_utilization;
157  }
158  }
159  }
160 
161  page->_update_frame_identifier = _current_frame_identifier;
162  page->_update_total_usage = 0;
163  }
164 
165  if (target_priority != page->_priority) {
166  page->_priority = min(max(target_priority, 0), LPP_TotalPriorities - 1);
167  ((AdaptiveLruPageDynamicList *)page)->remove_from_list();
168  ((AdaptiveLruPageDynamicList *)page)->insert_before(&_page_array[page->_priority]);
169  }
170 }
171 
172 ////////////////////////////////////////////////////////////////////
173 // Function: AdaptiveLruPage::enqueue_lru
174 // Access: Published
175 // Description: Adds the page to the LRU for the first time, or marks
176 // it recently-accessed if it has already been added.
177 //
178 // If lru is NULL, it means to remove this page from its
179 // LRU.
180 ////////////////////////////////////////////////////////////////////
183  if (lru != _lru && _lru != (AdaptiveLru *)NULL) {
184  // It was previously on a different LRU. Remove it first.
185  _lru->do_remove_page(this);
186  _lru = NULL;
187  }
188 
189  if (lru == _lru) {
190  if (_lru != (AdaptiveLru *)NULL) {
191  // It's already on this LRU. Access it.
192  _lru->do_access_page(this);
193  }
194  } else {
195  nassertv(lru != (AdaptiveLru *)NULL);
196  // Add it to a new LRU.
197  _lru = lru;
198 
199  _priority = AdaptiveLru::LPP_New;
200  _first_frame_identifier = _lru->_current_frame_identifier;
201  _current_frame_identifier = _lru->_current_frame_identifier;
202  _lru->do_add_page(this);
203  }
204 }
205 
206 ////////////////////////////////////////////////////////////////////
207 // Function: AdaptiveLru::count_active_size
208 // Access: Published
209 // Description: Returns the total size of the pages that were
210 // enqueued since the last call to begin_epoch().
211 ////////////////////////////////////////////////////////////////////
212 size_t AdaptiveLru::
214  size_t counted_size = 0;
215 
216  AdaptiveLruPageStaticList *node = (AdaptiveLruPageStaticList *)_static_list._next;
217  while (node != &_static_list) {
218  AdaptiveLruPage *page = (AdaptiveLruPage *)node;
219  if (page->_current_frame_identifier + 1 >= _current_frame_identifier) {
220  counted_size += page->_lru_size;
221  }
222  node = (AdaptiveLruPageStaticList *)node->_next;
223  }
224 
225  return counted_size;
226 }
227 
228 ////////////////////////////////////////////////////////////////////
229 // Function: AdaptiveLru::begin_epoch
230 // Access: Published
231 // Description: Marks the end of the previous epoch and the beginning
232 // of the next one. This will evict any objects that
233 // are pending eviction, and also update any internal
234 // bookkeeping.
235 ////////////////////////////////////////////////////////////////////
236 void AdaptiveLru::
238  LightMutexHolder holder(_lock);
239  do_partial_lru_update(_max_updates_per_frame);
240  if (_total_size > _max_size) {
241  do_evict_to(_max_size, false);
242  }
243 
244  _current_frame_identifier = ClockObject::get_global_clock()->get_frame_count();
245 }
246 
247 ////////////////////////////////////////////////////////////////////
248 // Function: AdaptiveLru::output
249 // Access: Published
250 // Description:
251 ////////////////////////////////////////////////////////////////////
252 void AdaptiveLru::
253 output(ostream &out) const {
254  LightMutexHolder holder(_lock);
255  out << "AdaptiveLru " << get_name()
256  << ", " << _total_size << " of " << _max_size;
257 }
258 
259 ////////////////////////////////////////////////////////////////////
260 // Function: AdaptiveLru::write
261 // Access: Published, Virtual
262 // Description:
263 ////////////////////////////////////////////////////////////////////
264 void AdaptiveLru::
265 write(ostream &out, int indent_level) const {
266  indent(out, indent_level) << *this << ":\n";
267 
268  // We write out the list backwards. Things we write out first are
269  // the freshest in the LRU. Things at the end of the list will be
270  // the next to be evicted.
271 
272  LightMutexHolder holder(_lock);
273 
274  int index;
275  for (index = 0; index < LPP_TotalPriorities; ++index) {
276  AdaptiveLruPageDynamicList *node = (AdaptiveLruPageDynamicList *)_page_array[index]._prev;
277  if (node != &_page_array[index]) {
278  indent(out, indent_level + 2) << "Priority " << index << ":\n";
279  while (node != &_page_array[index]) {
280  AdaptiveLruPage *page = (AdaptiveLruPage *)node;
281  indent(out, indent_level + 4) << *page;
282 
283  if (page->_current_frame_identifier + 1 >= _current_frame_identifier) {
284  out << " (active)";
285  }
286  out << "\n";
287 
288  node = (AdaptiveLruPageDynamicList *)node->_prev;
289  }
290  }
291  }
292 
293 #ifndef NDEBUG
294  ((AdaptiveLru *)this)->do_validate();
295 #endif
296 }
297 
298 ////////////////////////////////////////////////////////////////////
299 // Function: AdaptiveLru::do_add_page
300 // Access: Private
301 // Description: Adds a new page the the LRU.
302 ////////////////////////////////////////////////////////////////////
303 void AdaptiveLru::
305  nassertv(page != (AdaptiveLruPage *)NULL && page->_lru == this);
306  LightMutexHolder holder(_lock);
307 
308  _total_size += page->_lru_size;
309  ((AdaptiveLruPageDynamicList *)page)->insert_before(&_page_array[page->_priority]);
310  ((AdaptiveLruPageStaticList *)page)->insert_before(&_static_list);
311 }
312 
313 ////////////////////////////////////////////////////////////////////
314 // Function: AdaptiveLru::do_remove_page
315 // Access: Private
316 // Description: Removes a page from the LRU.
317 ////////////////////////////////////////////////////////////////////
318 void AdaptiveLru::
320  nassertv(page != (AdaptiveLruPage *)NULL && page->_lru == this);
321  LightMutexHolder holder(_lock);
322 
323  _total_size -= page->_lru_size;
324  ((AdaptiveLruPageDynamicList *)page)->remove_from_list();
325  ((AdaptiveLruPageStaticList *)page)->remove_from_list();
326 }
327 
328 ////////////////////////////////////////////////////////////////////
329 // Function: AdaptiveLru::do_access_page
330 // Access: Private
331 // Description: Marks a page accessed.
332 ////////////////////////////////////////////////////////////////////
333 void AdaptiveLru::
335  nassertv(page != (AdaptiveLruPage *)NULL && page->_lru == this);
336  LightMutexHolder holder(_lock);
337 
338  if (page->_current_frame_identifier == _current_frame_identifier) {
339  // This is the second or more time this page is accessed this
340  // frame.
341  ++(page->_current_frame_usage);
342 
343  } else {
344  // This page has not yet been accessed this frame. Update it.
345  page->_current_frame_identifier = _current_frame_identifier;
346  page->_last_frame_usage = page->_current_frame_usage;
347  page->_current_frame_usage = 1;
348  }
349 
350  // Move it to the tail of its priority list.
351  ((AdaptiveLruPageDynamicList *)page)->remove_from_list();
352  ((AdaptiveLruPageDynamicList *)page)->insert_before(&_page_array[page->_priority]);
353 
354  ++(page->_update_total_usage);
355 }
356 
357 ////////////////////////////////////////////////////////////////////
358 // Function: AdaptiveLru::do_evict_to
359 // Access: Private
360 // Description: Evicts pages until the LRU is within the indicated
361 // size. Assumes the lock is already held. If
362 // hard_evict is false, does not evict "active" pages
363 // that were added within this epoch.
364 ////////////////////////////////////////////////////////////////////
365 void AdaptiveLru::
366 do_evict_to(size_t target_size, bool hard_evict) {
367  int attempts;
368 
369  attempts = 0;
370  do {
371  // page out lower priority pages first
372  int index;
373  for (index = LPP_TotalPriorities - 1; index >= 0; index--) {
374 
375  // Store the current end of the list. If pages re-enqueue
376  // themselves during this traversal, we don't want to visit them
377  // twice.
378  AdaptiveLruPageDynamicList *end = (AdaptiveLruPageDynamicList *)_page_array[index]._prev;
379 
380  AdaptiveLruPageDynamicList *node = (AdaptiveLruPageDynamicList *)_page_array[index]._next;
381 
382  while (node != &_page_array[index]) {
384  AdaptiveLruPage *page = (AdaptiveLruPage *)node;
385 
386  if (attempts == 0 &&
387  (page->_current_frame_identifier + 1 >= _current_frame_identifier)) {
388  // avoid swapping out pages used in the current and last
389  // frame on the first attempt
390 
391  } else {
392  // We must release the lock while we call evict_lru().
393  _lock.release();
394  page->evict_lru();
395  _lock.acquire();
396 
397  if (_total_size <= target_size) {
398  // We've evicted enough to satisfy our target.
399  return;
400  }
401  }
402  if (node == end) {
403  // We've reached the former end of the list. Stop here;
404  // everything after has been re-queued.
405  break;
406  }
407  node = next;
408  }
409  }
410  attempts++;
411  } while (hard_evict && attempts < 2);
412 }
413 
414 ////////////////////////////////////////////////////////////////////
415 // Function: AdaptiveLru::do_validate
416 // Access: Private
417 // Description: Checks that the LRU is internally consistent. Assume
418 // the lock is already held.
419 ////////////////////////////////////////////////////////////////////
420 bool AdaptiveLru::
422  bool okflag = true;
424 
425  // First, walk through the dynamic pages.
426  size_t counted_size = 0;
427  int index;
428  for (index = 0; index < LPP_TotalPriorities; ++index) {
429  AdaptiveLruPageDynamicList *node = (AdaptiveLruPageDynamicList *)_page_array[index]._next;
430  while (node != &_page_array[index]) {
431  AdaptiveLruPage *page = (AdaptiveLruPage *)node;
432  counted_size += page->_lru_size;
433  if (page->_priority != index) {
434  nout << "page " << page << " has priority " << page->_priority
435  << " but is in queue " << index << "\n";
436  okflag = false;
437  }
438 
439  bool inserted_ok = pages.insert(page).second;
440  if (!inserted_ok) {
441  nout << "page " << page << " appears more than once in the dynamic index\n";
442  okflag = false;
443  }
444  node = (AdaptiveLruPageDynamicList *)node->_next;
445  }
446  }
447 
448  if (counted_size != _total_size) {
449  nout << "count " << counted_size << " bytes in dynamic index, but have " << _total_size << " on record\n";
450  okflag = false;
451  }
452 
453  // Now, walk through the static pages.
454  counted_size = 0;
455  AdaptiveLruPageStaticList *node = (AdaptiveLruPageStaticList *)_static_list._next;
456  while (node != &_static_list) {
457  AdaptiveLruPage *page = (AdaptiveLruPage *)node;
458  counted_size += page->_lru_size;
459 
460  if (pages.find(page) == pages.end()) {
461  nout << "page " << page << " appears in dynamic index, but not in static index (or multiple times in static index)\n";
462  okflag = false;
463  } else {
464  pages.erase(page);
465  }
466  node = (AdaptiveLruPageStaticList *)node->_next;
467  }
468 
469  if (counted_size != _total_size) {
470  nout << "count " << counted_size << " bytes in static index, but have " << _total_size << " on record\n";
471  okflag = false;
472  }
473 
474  return okflag;
475 }
476 
477 ////////////////////////////////////////////////////////////////////
478 // Function: AdaptiveLruPage::Constructor
479 // Access: Protected
480 // Description:
481 ////////////////////////////////////////////////////////////////////
482 AdaptiveLruPage::
483 AdaptiveLruPage(size_t lru_size) :
484  _lru(NULL),
485  _lru_size(lru_size),
486  _priority(0),
487  _first_frame_identifier(0),
488  _current_frame_identifier(0),
489  _update_frame_identifier(0),
490  _current_frame_usage(0),
491  _last_frame_usage(0),
492  _total_usage(0),
493  _update_total_usage(0),
494  _average_frame_utilization(1.0f)
495 {
496 }
497 
498 ////////////////////////////////////////////////////////////////////
499 // Function: AdaptiveLruPage::Copy Constructor
500 // Access: Protected
501 // Description:
502 ////////////////////////////////////////////////////////////////////
503 AdaptiveLruPage::
504 AdaptiveLruPage(const AdaptiveLruPage &copy) :
505  _lru(NULL),
506  _lru_size(copy._lru_size),
507  _priority(0),
508  _first_frame_identifier(0),
509  _current_frame_identifier(0),
510  _update_frame_identifier(0),
511  _current_frame_usage(0),
512  _last_frame_usage(0),
513  _total_usage(0),
514  _update_total_usage(0),
515  _average_frame_utilization(1.0f)
516 {
517 }
518 
519 ////////////////////////////////////////////////////////////////////
520 // Function: AdaptiveLruPage::Copy Assignment Operator
521 // Access: Protected
522 // Description:
523 ////////////////////////////////////////////////////////////////////
524 void AdaptiveLruPage::
525 operator = (const AdaptiveLruPage &copy) {
526  set_lru_size(copy.get_lru_size());
527 }
528 
529 ////////////////////////////////////////////////////////////////////
530 // Function: AdaptiveLruPage::Destructor
531 // Access: Published, Virtual
532 // Description:
533 ////////////////////////////////////////////////////////////////////
534 AdaptiveLruPage::
535 ~AdaptiveLruPage() {
536  if (_lru != NULL) {
537  dequeue_lru();
538  }
539 }
540 
541 ////////////////////////////////////////////////////////////////////
542 // Function: AdaptiveLruPage::evict_lru
543 // Access: Published, Virtual
544 // Description: Evicts the page from the LRU. Called internally when
545 // the LRU determines that it is full. May also be
546 // called externally when necessary to explicitly evict
547 // the page.
548 //
549 // It is legal for this method to either evict the page
550 // as requested, do nothing (in which case the eviction
551 // will be requested again at the next epoch), or
552 // requeue itself on the tail of the queue (in which
553 // case the eviction will be requested again much
554 // later).
555 ////////////////////////////////////////////////////////////////////
558  dequeue_lru();
559 }
560 
561 ////////////////////////////////////////////////////////////////////
562 // Function: AdaptiveLruPage::output
563 // Access: Published, Virtual
564 // Description:
565 ////////////////////////////////////////////////////////////////////
566 void AdaptiveLruPage::
567 output(ostream &out) const {
568  out << "page " << this << ", " << _lru_size;
569 }
570 
571 ////////////////////////////////////////////////////////////////////
572 // Function: AdaptiveLruPage::write
573 // Access: Published, Virtual
574 // Description:
575 ////////////////////////////////////////////////////////////////////
576 void AdaptiveLruPage::
577 write(ostream &out, int indent_level) const {
578  indent(out, indent_level) << *this << "\n";
579 }
580 
581 ////////////////////////////////////////////////////////////////////
582 // Function: AdaptiveLruPage::get_num_frames
583 // Access: Published
584 // Description: Returns the number of frames since the page was first
585 // added to its LRU. Returns 0 if it does not have an
586 // LRU.
587 ////////////////////////////////////////////////////////////////////
588 unsigned int AdaptiveLruPage::
589 get_num_frames() const {
590  if (_lru == (AdaptiveLru *)NULL) {
591  return 0;
592  }
593  return _lru->_current_frame_identifier - _first_frame_identifier;
594 }
595 
596 ////////////////////////////////////////////////////////////////////
597 // Function: AdaptiveLruPage::get_num_inactive_frames
598 // Access: Published
599 // Description: Returns the number of frames since the page was last
600 // accessed on its LRU. Returns 0 if it does not have
601 // an LRU.
602 ////////////////////////////////////////////////////////////////////
603 unsigned int AdaptiveLruPage::
605  if (_lru == (AdaptiveLru *)NULL) {
606  return 0;
607  }
608  return _lru->_current_frame_identifier - _current_frame_identifier;
609 }
610 
611 
612 #if 0
613 
614 ////////////////////////////////////////////////////////////////////
615 // Function: test_adaptive_lru
616 // Access:
617 // Description: Unit test function for Lru.
618 ////////////////////////////////////////////////////////////////////
619 void
620 test_adaptive_lru() {
621  int maximum_memory = 3000000;
622  AdaptiveLru *lru = new AdaptiveLru("test", maximum_memory);
623 
624  AdaptiveLruPage *lru_page_0;
625  AdaptiveLruPage *lru_page_1;
626  AdaptiveLruPage *lru_page_2;
627  AdaptiveLruPage *lru_page_3;
628  AdaptiveLruPage *lru_page_4;
629  AdaptiveLruPage *lru_page_5;
630 
631  lru_page_0 = new AdaptiveLruPage(1000000);
632  cerr << "created lru_page_0: " << lru_page_0 << "\n";
633  lru_page_0->enqueue_lru(lru);
634 
635  lru_page_1 = new AdaptiveLruPage(1000000);
636  cerr << "created lru_page_1: " << lru_page_1 << "\n";
637  lru_page_1->enqueue_lru(lru);
638 
639  lru_page_2 = new AdaptiveLruPage(1000000);
640  cerr << "created lru_page_2: " << lru_page_2 << "\n";
641  lru_page_2->enqueue_lru(lru);
642 
643  lru_page_3 = new AdaptiveLruPage(1000000);
644  cerr << "created lru_page_3: " << lru_page_3 << "\n";
645  lru_page_3->enqueue_lru(lru);
646 
647  lru_page_4 = new AdaptiveLruPage(1000000);
648  cerr << "created lru_page_4: " << lru_page_4 << "\n";
649  lru_page_4->enqueue_lru(lru);
650 
651  lru_page_5 = new AdaptiveLruPage(1000000);
652  cerr << "created lru_page_5: " << lru_page_5 << "\n";
653  lru_page_5->enqueue_lru(lru);
654 
655  int total_frames = 300;
656  int index;
657  for (index = 0; index < total_frames; index++) {
658  cerr << "FRAME " << index << "\n";
659 
660  lru->begin_epoch();
661 
662  if (index <= 5) {
663  lru_page_0->mark_used_lru(lru);
664  }
665 
666  lru_page_1->mark_used_lru(lru);
667  lru_page_1->mark_used_lru(lru);
668 
669  if (index & 0x01) {
670  lru_page_2->mark_used_lru(lru);
671  }
672 
673  if ((index % 10) == 0) {
674  lru_page_3->mark_used_lru(lru);
675  }
676 
677  if (index >= 100) {
678  lru_page_4->mark_used_lru(lru);
679  }
680 
681  if (index >= 200) {
682  lru_page_5->mark_used_lru(lru);
683  }
684 
685  if (!lru->validate()) {
686  cerr << "Failed validation\n";
687  break;
688  }
689  }
690 
691  delete lru;
692  delete lru_page_0;
693  delete lru_page_1;
694  delete lru_page_2;
695  delete lru_page_3;
696  delete lru_page_4;
697  delete lru_page_5;
698 }
699 
700 #endif // test_adaptive_lru
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
void release() const
Releases the lightMutex.
unsigned int get_num_inactive_frames() const
Returns the number of frames since the page was last accessed on its LRU.
void acquire() const
Grabs the lightMutex if it is available.
void do_remove_page(AdaptiveLruPage *page)
Removes a page from the LRU.
void set_lru_size(size_t lru_size)
Specifies the size of this page, presumably in bytes, although any unit is possible.
Definition: adaptiveLru.I:220
size_t get_lru_size() const
Returns the size of this page as reported to the LRU, presumably in bytes.
Definition: adaptiveLru.I:209
virtual void evict_lru()
Evicts the page from the LRU.
size_t count_active_size() const
Returns the total size of the pages that were enqueued since the last call to begin_epoch().
unsigned int get_num_frames() const
Returns the number of frames since the page was first added to its LRU.
bool do_validate()
Checks that the LRU is internally consistent.
void dequeue_lru()
Removes the page from its AdaptiveLru.
Definition: adaptiveLru.I:171
This just stores the pointers to implement a doubly-linked list of some kind of object.
void enqueue_lru(AdaptiveLru *lru)
Adds the page to the LRU for the first time, or marks it recently-accessed if it has already been add...
bool validate()
Checks that the LRU is internally self-consistent.
Definition: adaptiveLru.I:93
A base class for all things which can have a name.
Definition: namable.h:29
Similar to MutexHolder, but for a light mutex.
void begin_epoch()
Marks the end of the previous epoch and the beginning of the next one.
void update_page(AdaptiveLruPage *page)
This updates the page&#39;s average utilization.
int get_frame_count(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of times tick() has been called since the ClockObject was created, or since it was last reset.
Definition: clockObject.I:113
One atomic piece that may be managed by a AdaptiveLru chain.
Definition: adaptiveLru.h:145
void do_add_page(AdaptiveLruPage *page)
Adds a new page the the LRU.
A basic LRU-type algorithm, except that it is adaptive and attempts to avoid evicting pages that have...
Definition: adaptiveLru.h:49
void do_access_page(AdaptiveLruPage *page)
Marks a page accessed.
void do_partial_lru_update(int num_updates)
This only updates a number of pages up to the specified maximum_updates.
Definition: adaptiveLru.cxx:80
void do_evict_to(size_t target_size, bool hard_evict)
Evicts pages until the LRU is within the indicated size.
This is our own Panda specialization on the default STL set.
Definition: pset.h:52