pool CellInfo[,] to save massive amounts of memory (now uses only 512K for CellInfos on default-sized maps)

This commit is contained in:
Chris Forbes
2011-03-05 18:28:59 +13:00
parent 9f92f50597
commit 533df844d8
2 changed files with 88 additions and 39 deletions

View File

@@ -87,9 +87,10 @@ namespace OpenRA.Mods.RA.Move
{
using (new PerfSample("Pathfinder"))
{
using(search)
while (!search.queue.Empty)
{
var p = search.Expand( world );
var p = search.Expand(world);
if (search.heuristic(p) == 0)
return MakePath(search.cellInfo, p);
}
@@ -123,16 +124,18 @@ namespace OpenRA.Mods.RA.Move
{
using (new PerfSample("Pathfinder"))
{
using (fromSrc)
using (fromDest)
while (!fromSrc.queue.Empty && !fromDest.queue.Empty)
{
/* make some progress on the first search */
var p = fromSrc.Expand( world );
var p = fromSrc.Expand(world);
if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, p);
/* make some progress on the second search */
var q = fromDest.Expand( world );
var q = fromDest.Expand(world);
if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, q);

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Move
{
public class PathSearch
public class PathSearch : IDisposable
{
World world;
public CellInfo[ , ] cellInfo;
@@ -193,13 +193,45 @@ namespace OpenRA.Mods.RA.Move
return search;
}
static readonly Queue<CellInfo[,]> cellInfoPool = new Queue<CellInfo[,]>();
static CellInfo[,] GetFromPool()
{
lock (cellInfoPool)
return cellInfoPool.Dequeue();
}
static void PutBackIntoPool(CellInfo[,] ci)
{
lock (cellInfoPool)
cellInfoPool.Enqueue(ci);
}
CellInfo[ , ] InitCellInfo()
{
var cellInfo = new CellInfo[ world.Map.MapSize.X, world.Map.MapSize.Y ];
CellInfo[,] result = null;
while (cellInfoPool.Count > 0)
{
var cellInfo = GetFromPool();
if (cellInfo.GetUpperBound(0) != world.Map.MapSize.X - 1 ||
cellInfo.GetUpperBound(1) != world.Map.MapSize.Y - 1)
{
Game.Debug("Discarding old pooled CellInfo of wrong size.");
continue;
}
result = cellInfo;
break;
}
if (result == null)
result = new CellInfo[ world.Map.MapSize.X, world.Map.MapSize.Y ];
for( int x = 0 ; x < world.Map.MapSize.X ; x++ )
for( int y = 0 ; y < world.Map.MapSize.Y ; y++ )
cellInfo[ x, y ] = new CellInfo( int.MaxValue, new int2( x, y ), false );
return cellInfo;
result[ x, y ] = new CellInfo( int.MaxValue, new int2( x, y ), false );
return result;
}
public static Func<int2, int> DefaultEstimator( int2 destination )
@@ -212,5 +244,19 @@ namespace OpenRA.Mods.RA.Move
return (3400 * diag / 24) + (100 * straight);
};
}
bool disposed;
public void Dispose()
{
if (disposed)
return;
disposed = true;
GC.SuppressFinalize(this);
PutBackIntoPool(cellInfo);
cellInfo = null;
}
~PathSearch() { Dispose(); }
}
}