summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2008-04-21 10:45:11 +0200
committerMichel Dänzer <michel@tungstengraphics.com>2008-04-21 10:45:11 +0200
commit6c95fae1e9d6b0eb64bc78eced05a6e9f5faf02e (patch)
treef416d1c8382e0281653b6ca0dcc0f08885210b54
parent40c6be1408a1f0b236fdb28af27ae18aea0d578f (diff)
EXA: Offscreen memory eviction improvements.
* Make sure available areas are considered to have no eviction cost. This seems to help for https://bugs.freedesktop.org/show_bug.cgi?id=15513 but I'm afraid that may just be coincidence. * Only calculate eviction cost of each area once for each eviction pass. Safeguard against potential (though unlikely) division by zero. * Cosmetic enhancements: Name eviction cost related variables 'cost' instead of 'score' to emphasize that smaller values are better, update Doxygen file comment to the way eviction works now.
-rw-r--r--exa/exa.h2
-rw-r--r--exa/exa_offscreen.c49
2 files changed, 36 insertions, 15 deletions
diff --git a/exa/exa.h b/exa/exa.h
index 97ae6c0a5..256209418 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -64,6 +64,8 @@ struct _ExaOffscreenArea {
ExaOffscreenState state;
ExaOffscreenArea *next;
+
+ unsigned eviction_cost;
};
/**
diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c
index 85b538896..4aaa2c132 100644
--- a/exa/exa_offscreen.c
+++ b/exa/exa_offscreen.c
@@ -21,11 +21,9 @@
*/
/** @file
- * This allocator allocates blocks of memory by maintaining a list of areas
- * and a score for each area. As an area is marked used, its score is
- * incremented, and periodically all of the areas have their scores decayed by
- * a fraction. When allocating, the contiguous block of areas with the minimum
- * score is found and evicted in order to make room for the new allocation.
+ * This allocator allocates blocks of memory by maintaining a list of areas.
+ * When allocating, the contiguous block of areas with the minimum eviction
+ * cost is found and evicted in order to make room for the new allocation.
*/
#include "exa_priv.h"
@@ -71,19 +69,36 @@ ExaOffscreenKickOut (ScreenPtr pScreen, ExaOffscreenArea *area)
return exaOffscreenFree (pScreen, area);
}
-#define AREA_SCORE(area) (area->size / (double)(pExaScr->offScreenCounter - area->last_use))
+static void
+exaUpdateEvictionCost(ExaOffscreenArea *area, unsigned offScreenCounter)
+{
+ unsigned age;
+
+ if (area->state == ExaOffscreenAvail)
+ return;
+
+ age = offScreenCounter - area->last_use;
+
+ /* This is unlikely to happen, but could result in a division by zero... */
+ if (age > (UINT_MAX / 2)) {
+ age = UINT_MAX / 2;
+ area->last_use = offScreenCounter - age;
+ }
+
+ area->eviction_cost = area->size / age;
+}
static ExaOffscreenArea *
exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align)
{
ExaOffscreenArea *begin, *end, *best;
- double score, best_score;
+ unsigned cost, best_cost;
int avail, real_size, tmp;
- best_score = UINT_MAX;
+ best_cost = UINT_MAX;
begin = end = pExaScr->info->offScreenAreas;
avail = 0;
- score = 0;
+ cost = 0;
best = 0;
while (end != NULL)
@@ -106,23 +121,24 @@ exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align)
if (end->state == ExaOffscreenLocked) {
/* Can't more room here, restart after this locked area */
avail = 0;
- score = 0;
+ cost = 0;
begin = end;
goto restart;
}
avail += end->size;
- score += AREA_SCORE(end);
+ exaUpdateEvictionCost(end, pExaScr->offScreenCounter);
+ cost += end->eviction_cost;
end = end->next;
}
- /* Check the score, update best */
- if (avail >= real_size && score < best_score) {
+ /* Check the cost, update best */
+ if (avail >= real_size && cost < best_cost) {
best = begin;
- best_score = score;
+ best_cost = cost;
}
avail -= begin->size;
- score -= AREA_SCORE(begin);
+ cost -= begin->eviction_cost;
begin = begin->next;
}
@@ -244,6 +260,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
new_area->state = ExaOffscreenAvail;
new_area->save = NULL;
new_area->last_use = 0;
+ new_area->eviction_cost = 0;
new_area->next = area->next;
area->next = new_area;
area->size = real_size;
@@ -409,6 +426,7 @@ exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
area->state = ExaOffscreenAvail;
area->save = NULL;
area->last_use = 0;
+ area->eviction_cost = 0;
/*
* Find previous area
*/
@@ -474,6 +492,7 @@ exaOffscreenInit (ScreenPtr pScreen)
area->save = NULL;
area->next = NULL;
area->last_use = 0;
+ area->eviction_cost = 0;
/* Add it to the free areas */
pExaScr->info->offScreenAreas = area;