Skip to content

Commit

Permalink
Optimize memory management in the deferred mobj spawn system. Allocat…
Browse files Browse the repository at this point in the history
…e spawn queue nodes in batches of 32. Maintain a list of unused nodes to be recycled later.
  • Loading branch information
danij committed Jun 17, 2009
1 parent d174d45 commit d94d6b5
Showing 1 changed file with 71 additions and 6 deletions.
77 changes: 71 additions & 6 deletions doomsday/plugins/common/src/p_actor.c
Expand Up @@ -85,7 +85,7 @@ typedef struct spawnqueuenode_s {

// PRIVATE DATA DEFINITIONS ------------------------------------------------

static spawnqueuenode_t* spawnQueueHead = NULL;
static spawnqueuenode_t* spawnQueueHead = NULL, *unusedNodes = NULL;

// CODE --------------------------------------------------------------------

Expand Down Expand Up @@ -332,6 +332,71 @@ void P_RipperBlood(mobj_t* actor)
}
}

static spawnqueuenode_t* allocateNode(void)
{
#define SPAWNQUEUENODE_BATCHSIZE 32

spawnqueuenode_t* n;

if(unusedNodes)
{ // There are existing nodes we can re-use.
n = unusedNodes;
unusedNodes = unusedNodes->next;
n->next = NULL;
}
else
{ // We need to allocate more.
size_t i;
spawnqueuenode_t* storage =
Z_Malloc(sizeof(*n) * SPAWNQUEUENODE_BATCHSIZE, PU_STATIC, 0);

// Add all but one to the unused node list.
for(i = 0; i < SPAWNQUEUENODE_BATCHSIZE-1; ++i)
{
n = storage++;
n->next = unusedNodes;
unusedNodes = n;
}

n = storage;
}

return n;

#undef SPAWNQUEUENODE_BATCHSIZE
}

static void freeNode(spawnqueuenode_t* node, boolean recycle)
{
// Find this node in the spawn queue and unlink it if found.
if(spawnQueueHead)
{
if(spawnQueueHead == node)
{
spawnQueueHead = spawnQueueHead->next;
}
else
{
spawnqueuenode_t* n;

for(n = spawnQueueHead; n->next; n = n->next)
{
if(n->next == node)
n->next = n->next->next;
}
}
}

if(recycle)
{ // Recycle this node for later use.
node->next = unusedNodes;
unusedNodes = node;
return;
}

Z_Free(node);
}

static spawnqueuenode_t* dequeueSpawn(void)
{
spawnqueuenode_t* n = spawnQueueHead;
Expand All @@ -342,14 +407,14 @@ static spawnqueuenode_t* dequeueSpawn(void)
return n;
}

static void emptySpawnQueue(void)
static void emptySpawnQueue(boolean recycle)
{
if(spawnQueueHead)
{
spawnqueuenode_t* n;

while((n = dequeueSpawn()))
Z_Free(n);
freeNode(n, recycle);
}

spawnQueueHead = NULL;
Expand All @@ -360,7 +425,7 @@ static void enqueueSpawn(int minTics, mobjtype_t type, float x, float y,
void (*callback) (mobj_t* mo, void* context),
void* context)
{
spawnqueuenode_t* n = Z_Malloc(sizeof(*n), PU_MAP, 0);
spawnqueuenode_t* n = allocateNode();

n->type = type;
n->pos[VX] = x;
Expand Down Expand Up @@ -427,7 +492,7 @@ static mobj_t* doDeferredSpawn(void)
n->callback(mo, n->context);
}

Z_Free(n);
freeNode(n, true);
}

return mo;
Expand Down Expand Up @@ -491,5 +556,5 @@ void P_DoDeferredSpawns(void)

void P_PurgeDeferredSpawns(void)
{
emptySpawnQueue();
emptySpawnQueue(true);
}

0 comments on commit d94d6b5

Please sign in to comment.