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,12 +87,13 @@ namespace OpenRA.Mods.RA.Move
{ {
using (new PerfSample("Pathfinder")) using (new PerfSample("Pathfinder"))
{ {
while (!search.queue.Empty) using(search)
{ while (!search.queue.Empty)
var p = search.Expand( world ); {
if (search.heuristic(p) == 0) var p = search.Expand(world);
return MakePath(search.cellInfo, p); if (search.heuristic(p) == 0)
} return MakePath(search.cellInfo, p);
}
// no path exists // no path exists
return new List<int2>(); return new List<int2>();
@@ -113,33 +114,35 @@ namespace OpenRA.Mods.RA.Move
ret.Add(pathNode); ret.Add(pathNode);
CheckSanePath(ret); CheckSanePath(ret);
return ret; return ret;
} }
public List<int2> FindBidiPath( /* searches from both ends toward each other */ public List<int2> FindBidiPath( /* searches from both ends toward each other */
PathSearch fromSrc, PathSearch fromSrc,
PathSearch fromDest) PathSearch fromDest)
{ {
using (new PerfSample("Pathfinder")) using (new PerfSample("Pathfinder"))
{ {
while (!fromSrc.queue.Empty && !fromDest.queue.Empty) using (fromSrc)
{ using (fromDest)
/* make some progress on the first search */ while (!fromSrc.queue.Empty && !fromDest.queue.Empty)
var p = fromSrc.Expand( world ); {
/* make some progress on the first search */
if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity) var p = fromSrc.Expand(world);
return MakeBidiPath(fromSrc, fromDest, p);
if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
/* make some progress on the second search */ return MakeBidiPath(fromSrc, fromDest, p);
var q = fromDest.Expand( world );
/* make some progress on the second search */
if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity) var q = fromDest.Expand(world);
return MakeBidiPath(fromSrc, fromDest, q);
} if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, q);
return new List<int2>(); }
}
return new List<int2>();
}
} }
static List<int2> MakeBidiPath(PathSearch a, PathSearch b, int2 p) static List<int2> MakeBidiPath(PathSearch a, PathSearch b, int2 p)

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Move namespace OpenRA.Mods.RA.Move
{ {
public class PathSearch public class PathSearch : IDisposable
{ {
World world; World world;
public CellInfo[ , ] cellInfo; public CellInfo[ , ] cellInfo;
@@ -191,15 +191,47 @@ namespace OpenRA.Mods.RA.Move
search.AddInitialCell( sl ); search.AddInitialCell( sl );
return search; 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() 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 x = 0 ; x < world.Map.MapSize.X ; x++ )
for( int y = 0 ; y < world.Map.MapSize.Y ; y++ ) for( int y = 0 ; y < world.Map.MapSize.Y ; y++ )
cellInfo[ x, y ] = new CellInfo( int.MaxValue, new int2( x, y ), false ); result[ x, y ] = new CellInfo( int.MaxValue, new int2( x, y ), false );
return cellInfo;
return result;
} }
public static Func<int2, int> DefaultEstimator( int2 destination ) public static Func<int2, int> DefaultEstimator( int2 destination )
@@ -211,6 +243,20 @@ namespace OpenRA.Mods.RA.Move
int straight = Math.Abs( d.X - d.Y ); int straight = Math.Abs( d.X - d.Y );
return (3400 * diag / 24) + (100 * straight); 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(); }
} }
} }