more GC optimizations

master
Evan Hemsley 2019-10-23 17:31:22 -07:00
parent a08a39c353
commit 6b257a9661
5 changed files with 74 additions and 41 deletions

View File

@ -280,7 +280,7 @@ namespace MoonTools.Core.Graph
s.Remove(neighbor);
t.Add(neighbor);
if (s.Count == 0) { lexicographicSets.Remove(s); replacedSets.Remove(s); }
if (s.Count == 0) { lexicographicSets.Remove(s); replacedSets.Remove(s); s.Dispose(); }
}
}
}
@ -298,20 +298,20 @@ namespace MoonTools.Core.Graph
{
return PostorderNodeDFS().Reverse();
}
readonly Dictionary<TNode, uint> preorder = new Dictionary<TNode, uint>();
readonly Dictionary<TNode, uint> lowlink = new Dictionary<TNode, uint>();
readonly Dictionary<TNode, bool> sccFound = new Dictionary<TNode, bool>();
readonly Stack<TNode> sccQueue = new Stack<TNode>();
readonly List<List<TNode>> sccResult = new List<List<TNode>>();
List<PooledList<TNode>> sccs = new List<PooledList<TNode>>();
public IEnumerable<IEnumerable<TNode>> StronglyConnectedComponents()
{
preorder.Clear();
lowlink.Clear();
sccFound.Clear();
sccQueue.Clear();
sccResult.Clear();
foreach (var scc in sccs)
{
scc.Dispose();
}
sccs.Clear();
var preorder = new PooledDictionary<TNode, uint>();
var lowlink = new PooledDictionary<TNode, uint>();
var sccFound = new PooledDictionary<TNode, bool>();
var sccQueue = new PooledStack<TNode>();
uint preorderCounter = 0;
@ -364,7 +364,7 @@ namespace MoonTools.Core.Graph
if (lowlink[v] == preorder[v])
{
sccFound[v] = true;
var scc = new List<TNode>
var scc = new PooledList<TNode>
{
v
};
@ -374,7 +374,9 @@ namespace MoonTools.Core.Graph
sccFound[k] = true;
scc.Add(k);
}
sccResult.Add(scc);
sccs.Add(scc);
yield return scc;
}
else
{
@ -384,8 +386,6 @@ namespace MoonTools.Core.Graph
}
}
}
return sccResult;
}
public IEnumerable<IEnumerable<TNode>> SimpleCycles()

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Collections.Pooled;
using MoreLinq;
namespace MoonTools.Core.Graph
@ -12,13 +13,6 @@ namespace MoonTools.Core.Graph
protected Dictionary<(TNode, TNode), TEdgeData> edgeToEdgeData = new Dictionary<(TNode, TNode), TEdgeData>();
protected Dictionary<(TNode, TNode), int> weights = new Dictionary<(TNode, TNode), int>();
// store search sets to prevent GC
protected HashSet<TNode> openSet = new HashSet<TNode>();
protected HashSet<TNode> closedSet = new HashSet<TNode>();
protected Dictionary<TNode, int> gScore = new Dictionary<TNode, int>();
protected Dictionary<TNode, int> fScore = new Dictionary<TNode, int>();
protected Dictionary<TNode, TNode> cameFrom = new Dictionary<TNode, TNode>();
public IEnumerable<TNode> Nodes => nodes;
public void AddNode(TNode node)
@ -107,7 +101,7 @@ namespace MoonTools.Core.Graph
return edgeToEdgeData[(v, u)];
}
private IEnumerable<(TNode, TNode)> ReconstructPath(Dictionary<TNode, TNode> cameFrom, TNode currentNode)
private IEnumerable<(TNode, TNode)> ReconstructPath(PooledDictionary<TNode, TNode> cameFrom, TNode currentNode)
{
while (cameFrom.ContainsKey(currentNode))
{
@ -121,11 +115,11 @@ namespace MoonTools.Core.Graph
{
CheckNodes(start, end);
openSet.Clear();
closedSet.Clear();
gScore.Clear();
fScore.Clear();
cameFrom.Clear();
var openSet = new PooledSet<TNode>(ClearMode.Always);
var closedSet = new PooledSet<TNode>(ClearMode.Always);
var gScore = new PooledDictionary<TNode, int>(ClearMode.Always);
var fScore = new PooledDictionary<TNode, int>(ClearMode.Always);
var cameFrom = new PooledDictionary<TNode, TNode>(ClearMode.Always);
openSet.Add(start);
@ -138,7 +132,19 @@ namespace MoonTools.Core.Graph
if (currentNode.Equals(end))
{
return ReconstructPath(cameFrom, currentNode).Reverse();
openSet.Dispose();
closedSet.Dispose();
gScore.Dispose();
fScore.Dispose();
foreach (var edge in ReconstructPath(cameFrom, currentNode).Reverse())
{
yield return edge;
}
cameFrom.Dispose();
yield break;
}
openSet.Remove(currentNode);
@ -163,7 +169,13 @@ namespace MoonTools.Core.Graph
}
}
return Enumerable.Empty<(TNode, TNode)>();
openSet.Dispose();
closedSet.Dispose();
gScore.Dispose();
fScore.Dispose();
cameFrom.Dispose();
yield break;
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Collections.Pooled;
using MoreLinq;
namespace MoonTools.Core.Graph
@ -120,7 +121,7 @@ namespace MoonTools.Core.Graph
return edgeToEdgeData[id];
}
private IEnumerable<Guid> ReconstructPath(Dictionary<TNode, Guid> cameFrom, TNode currentNode)
private IEnumerable<Guid> ReconstructPath(PooledDictionary<TNode, Guid> cameFrom, TNode currentNode)
{
while (cameFrom.ContainsKey(currentNode))
{
@ -135,11 +136,11 @@ namespace MoonTools.Core.Graph
{
CheckNodes(start, end);
openSet.Clear();
closedSet.Clear();
gScore.Clear();
fScore.Clear();
cameFrom.Clear();
var openSet = new PooledSet<TNode>(ClearMode.Always);
var closedSet = new PooledSet<TNode>(ClearMode.Always);
var gScore = new PooledDictionary<TNode, int>(ClearMode.Always);
var fScore = new PooledDictionary<TNode, int>(ClearMode.Always);
var cameFrom = new PooledDictionary<TNode, Guid>(ClearMode.Always);
openSet.Add(start);
@ -152,7 +153,19 @@ namespace MoonTools.Core.Graph
if (currentNode.Equals(end))
{
return ReconstructPath(cameFrom, currentNode).Reverse();
openSet.Dispose();
closedSet.Dispose();
gScore.Dispose();
fScore.Dispose();
foreach (var edgeID in ReconstructPath(cameFrom, currentNode).Reverse())
{
yield return edgeID;
}
cameFrom.Dispose();
yield break;
}
openSet.Remove(currentNode);
@ -178,7 +191,13 @@ namespace MoonTools.Core.Graph
}
}
return Enumerable.Empty<Guid>();
openSet.Dispose();
closedSet.Dispose();
gScore.Dispose();
fScore.Dispose();
cameFrom.Dispose();
yield break;
}
}
}

View File

@ -218,7 +218,8 @@ namespace Tests
.And
.HaveCount(3);
myGraph.Invoking(x => x.AStarShortestPath('a', 'z', (x, y) => 15)).Should().Throw<System.ArgumentException>();
// have to call Count() because otherwise the lazy evaluation wont trigger
myGraph.Invoking(x => x.AStarShortestPath('a', 'z', (x, y) => 1).Count()).Should().Throw<System.ArgumentException>();
}
}
}

View File

@ -248,7 +248,8 @@ namespace Tests
.And
.HaveCount(3);
myGraph.Invoking(x => x.AStarShortestPath('a', 'z', (x, y) => 15)).Should().Throw<System.ArgumentException>();
// have to call Count() because otherwise the lazy evaluation wont trigger
myGraph.Invoking(x => x.AStarShortestPath('a', 'z', (x, y) => 1).Count()).Should().Throw<System.ArgumentException>();
}
}
}