diff options
author | Michel Dänzer <michel@tungstengraphics.com> | 2008-04-21 10:45:11 +0200 |
---|---|---|
committer | Michel Dänzer <michel@tungstengraphics.com> | 2008-04-21 10:45:11 +0200 |
commit | 6c95fae1e9d6b0eb64bc78eced05a6e9f5faf02e (patch) | |
tree | f416d1c8382e0281653b6ca0dcc0f08885210b54 /exa/exa_offscreen.c | |
parent | 40c6be1408a1f0b236fdb28af27ae18aea0d578f (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.
Diffstat (limited to 'exa/exa_offscreen.c')
-rw-r--r-- | exa/exa_offscreen.c | 49 |
1 files changed, 34 insertions, 15 deletions
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; |