EXA: Improve the algorithm used for tracking offscreen pixmap use.
Replace the current score keeping algorithm with a rolling counter that's incremented in ExaOffscreenMarkUsed, with the previous value being stored in the area. exaOffscreenAlloc uses the difference between the counter value and the value in the area when deciding which area to evict. It now also takes the size of the areas into account, and favors evicting smaller areas. The credit for these ideas goes to Michel Dänzer.
This commit is contained in:
parent
7034484f08
commit
93d876891d
|
@ -56,7 +56,7 @@ struct _ExaOffscreenArea {
|
||||||
int base_offset; /* allocation base */
|
int base_offset; /* allocation base */
|
||||||
int offset; /* aligned offset */
|
int offset; /* aligned offset */
|
||||||
int size; /* total allocation size */
|
int size; /* total allocation size */
|
||||||
int score;
|
unsigned last_use;
|
||||||
pointer privData;
|
pointer privData;
|
||||||
|
|
||||||
ExaOffscreenSaveProc save;
|
ExaOffscreenSaveProc save;
|
||||||
|
|
|
@ -71,6 +71,8 @@ ExaOffscreenKickOut (ScreenPtr pScreen, ExaOffscreenArea *area)
|
||||||
return exaOffscreenFree (pScreen, area);
|
return exaOffscreenFree (pScreen, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define AREA_SCORE(area) (area->size / (double)(pExaScr->offScreenCounter - area->last_use))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* exaOffscreenAlloc allocates offscreen memory
|
* exaOffscreenAlloc allocates offscreen memory
|
||||||
*
|
*
|
||||||
|
@ -98,7 +100,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
{
|
{
|
||||||
ExaOffscreenArea *area, *begin, *best;
|
ExaOffscreenArea *area, *begin, *best;
|
||||||
ExaScreenPriv (pScreen);
|
ExaScreenPriv (pScreen);
|
||||||
int tmp, real_size = 0, best_score;
|
int tmp, real_size = 0;
|
||||||
#if DEBUG_OFFSCREEN
|
#if DEBUG_OFFSCREEN
|
||||||
static int number = 0;
|
static int number = 0;
|
||||||
ErrorF("================= ============ allocating a new pixmap %d\n", ++number);
|
ErrorF("================= ============ allocating a new pixmap %d\n", ++number);
|
||||||
|
@ -143,6 +145,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
if (!area)
|
if (!area)
|
||||||
{
|
{
|
||||||
|
double best_score;
|
||||||
/*
|
/*
|
||||||
* Kick out existing users to make space.
|
* Kick out existing users to make space.
|
||||||
*
|
*
|
||||||
|
@ -151,11 +154,12 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
|
|
||||||
/* prev points at the first object to boot */
|
/* prev points at the first object to boot */
|
||||||
best = NULL;
|
best = NULL;
|
||||||
best_score = INT_MAX;
|
best_score = UINT_MAX;
|
||||||
for (begin = pExaScr->info->offScreenAreas; begin != NULL;
|
for (begin = pExaScr->info->offScreenAreas; begin != NULL;
|
||||||
begin = begin->next)
|
begin = begin->next)
|
||||||
{
|
{
|
||||||
int avail, score;
|
int avail;
|
||||||
|
double score;
|
||||||
ExaOffscreenArea *scan;
|
ExaOffscreenArea *scan;
|
||||||
|
|
||||||
if (begin->state == ExaOffscreenLocked)
|
if (begin->state == ExaOffscreenLocked)
|
||||||
|
@ -177,8 +181,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
begin = scan;
|
begin = scan;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Score should only be non-zero for ExaOffscreenRemovable */
|
score += AREA_SCORE(scan);
|
||||||
score += scan->score;
|
|
||||||
avail += scan->size;
|
avail += scan->size;
|
||||||
if (avail >= real_size)
|
if (avail >= real_size)
|
||||||
break;
|
break;
|
||||||
|
@ -230,7 +233,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
new_area->size = area->size - real_size;
|
new_area->size = area->size - real_size;
|
||||||
new_area->state = ExaOffscreenAvail;
|
new_area->state = ExaOffscreenAvail;
|
||||||
new_area->save = NULL;
|
new_area->save = NULL;
|
||||||
new_area->score = 0;
|
new_area->last_use = 0;
|
||||||
new_area->next = area->next;
|
new_area->next = area->next;
|
||||||
area->next = new_area;
|
area->next = new_area;
|
||||||
area->size = real_size;
|
area->size = real_size;
|
||||||
|
@ -244,7 +247,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
|
||||||
area->state = ExaOffscreenRemovable;
|
area->state = ExaOffscreenRemovable;
|
||||||
area->privData = privData;
|
area->privData = privData;
|
||||||
area->save = save;
|
area->save = save;
|
||||||
area->score = 0;
|
area->last_use = pExaScr->offScreenCounter++;
|
||||||
area->offset = (area->base_offset + align - 1);
|
area->offset = (area->base_offset + align - 1);
|
||||||
area->offset -= area->offset % align;
|
area->offset -= area->offset % align;
|
||||||
|
|
||||||
|
@ -395,7 +398,7 @@ exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
|
||||||
|
|
||||||
area->state = ExaOffscreenAvail;
|
area->state = ExaOffscreenAvail;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->score = 0;
|
area->last_use = 0;
|
||||||
/*
|
/*
|
||||||
* Find previous area
|
* Find previous area
|
||||||
*/
|
*/
|
||||||
|
@ -427,23 +430,11 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap)
|
||||||
{
|
{
|
||||||
ExaPixmapPriv (pPixmap);
|
ExaPixmapPriv (pPixmap);
|
||||||
ExaScreenPriv (pPixmap->drawable.pScreen);
|
ExaScreenPriv (pPixmap->drawable.pScreen);
|
||||||
static int iter = 0;
|
|
||||||
|
|
||||||
if (!pExaPixmap || !pExaPixmap->area)
|
if (!pExaPixmap || !pExaPixmap->area)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* The numbers here are arbitrary. We may want to tune these. */
|
pExaPixmap->area->last_use = pExaScr->offScreenCounter++;
|
||||||
pExaPixmap->area->score += 100;
|
|
||||||
if (++iter == 10) {
|
|
||||||
ExaOffscreenArea *area;
|
|
||||||
for (area = pExaScr->info->offScreenAreas; area != NULL;
|
|
||||||
area = area->next)
|
|
||||||
{
|
|
||||||
if (area->state == ExaOffscreenRemovable)
|
|
||||||
area->score = (area->score * 7) / 8;
|
|
||||||
}
|
|
||||||
iter = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -472,10 +463,11 @@ exaOffscreenInit (ScreenPtr pScreen)
|
||||||
area->size = pExaScr->info->memorySize - area->base_offset;
|
area->size = pExaScr->info->memorySize - area->base_offset;
|
||||||
area->save = NULL;
|
area->save = NULL;
|
||||||
area->next = NULL;
|
area->next = NULL;
|
||||||
area->score = 0;
|
area->last_use = 0;
|
||||||
|
|
||||||
/* Add it to the free areas */
|
/* Add it to the free areas */
|
||||||
pExaScr->info->offScreenAreas = area;
|
pExaScr->info->offScreenAreas = area;
|
||||||
|
pExaScr->offScreenCounter = 1;
|
||||||
|
|
||||||
ExaOffscreenValidate (pScreen);
|
ExaOffscreenValidate (pScreen);
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ typedef struct {
|
||||||
Bool checkDirtyCorrectness;
|
Bool checkDirtyCorrectness;
|
||||||
unsigned disableFbCount;
|
unsigned disableFbCount;
|
||||||
Bool optimize_migration;
|
Bool optimize_migration;
|
||||||
|
unsigned offScreenCounter;
|
||||||
} ExaScreenPrivRec, *ExaScreenPrivPtr;
|
} ExaScreenPrivRec, *ExaScreenPrivPtr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue