more GC optimizations
parent
a08a39c353
commit
6b257a9661
|
@ -280,7 +280,7 @@ namespace MoonTools.Core.Graph
|
||||||
|
|
||||||
s.Remove(neighbor);
|
s.Remove(neighbor);
|
||||||
t.Add(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();
|
return PostorderNodeDFS().Reverse();
|
||||||
}
|
}
|
||||||
|
List<PooledList<TNode>> sccs = new List<PooledList<TNode>>();
|
||||||
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>>();
|
|
||||||
|
|
||||||
public IEnumerable<IEnumerable<TNode>> StronglyConnectedComponents()
|
public IEnumerable<IEnumerable<TNode>> StronglyConnectedComponents()
|
||||||
{
|
{
|
||||||
preorder.Clear();
|
foreach (var scc in sccs)
|
||||||
lowlink.Clear();
|
{
|
||||||
sccFound.Clear();
|
scc.Dispose();
|
||||||
sccQueue.Clear();
|
}
|
||||||
sccResult.Clear();
|
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;
|
uint preorderCounter = 0;
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ namespace MoonTools.Core.Graph
|
||||||
if (lowlink[v] == preorder[v])
|
if (lowlink[v] == preorder[v])
|
||||||
{
|
{
|
||||||
sccFound[v] = true;
|
sccFound[v] = true;
|
||||||
var scc = new List<TNode>
|
var scc = new PooledList<TNode>
|
||||||
{
|
{
|
||||||
v
|
v
|
||||||
};
|
};
|
||||||
|
@ -374,7 +374,9 @@ namespace MoonTools.Core.Graph
|
||||||
sccFound[k] = true;
|
sccFound[k] = true;
|
||||||
scc.Add(k);
|
scc.Add(k);
|
||||||
}
|
}
|
||||||
sccResult.Add(scc);
|
|
||||||
|
sccs.Add(scc);
|
||||||
|
yield return scc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -384,8 +386,6 @@ namespace MoonTools.Core.Graph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sccResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IEnumerable<TNode>> SimpleCycles()
|
public IEnumerable<IEnumerable<TNode>> SimpleCycles()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Collections.Pooled;
|
||||||
using MoreLinq;
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MoonTools.Core.Graph
|
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), TEdgeData> edgeToEdgeData = new Dictionary<(TNode, TNode), TEdgeData>();
|
||||||
protected Dictionary<(TNode, TNode), int> weights = new Dictionary<(TNode, TNode), int>();
|
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 IEnumerable<TNode> Nodes => nodes;
|
||||||
|
|
||||||
public void AddNode(TNode node)
|
public void AddNode(TNode node)
|
||||||
|
@ -107,7 +101,7 @@ namespace MoonTools.Core.Graph
|
||||||
return edgeToEdgeData[(v, u)];
|
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))
|
while (cameFrom.ContainsKey(currentNode))
|
||||||
{
|
{
|
||||||
|
@ -121,11 +115,11 @@ namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
CheckNodes(start, end);
|
CheckNodes(start, end);
|
||||||
|
|
||||||
openSet.Clear();
|
var openSet = new PooledSet<TNode>(ClearMode.Always);
|
||||||
closedSet.Clear();
|
var closedSet = new PooledSet<TNode>(ClearMode.Always);
|
||||||
gScore.Clear();
|
var gScore = new PooledDictionary<TNode, int>(ClearMode.Always);
|
||||||
fScore.Clear();
|
var fScore = new PooledDictionary<TNode, int>(ClearMode.Always);
|
||||||
cameFrom.Clear();
|
var cameFrom = new PooledDictionary<TNode, TNode>(ClearMode.Always);
|
||||||
|
|
||||||
openSet.Add(start);
|
openSet.Add(start);
|
||||||
|
|
||||||
|
@ -138,7 +132,19 @@ namespace MoonTools.Core.Graph
|
||||||
|
|
||||||
if (currentNode.Equals(end))
|
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);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Collections.Pooled;
|
||||||
using MoreLinq;
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MoonTools.Core.Graph
|
namespace MoonTools.Core.Graph
|
||||||
|
@ -120,7 +121,7 @@ namespace MoonTools.Core.Graph
|
||||||
return edgeToEdgeData[id];
|
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))
|
while (cameFrom.ContainsKey(currentNode))
|
||||||
{
|
{
|
||||||
|
@ -135,11 +136,11 @@ namespace MoonTools.Core.Graph
|
||||||
{
|
{
|
||||||
CheckNodes(start, end);
|
CheckNodes(start, end);
|
||||||
|
|
||||||
openSet.Clear();
|
var openSet = new PooledSet<TNode>(ClearMode.Always);
|
||||||
closedSet.Clear();
|
var closedSet = new PooledSet<TNode>(ClearMode.Always);
|
||||||
gScore.Clear();
|
var gScore = new PooledDictionary<TNode, int>(ClearMode.Always);
|
||||||
fScore.Clear();
|
var fScore = new PooledDictionary<TNode, int>(ClearMode.Always);
|
||||||
cameFrom.Clear();
|
var cameFrom = new PooledDictionary<TNode, Guid>(ClearMode.Always);
|
||||||
|
|
||||||
openSet.Add(start);
|
openSet.Add(start);
|
||||||
|
|
||||||
|
@ -152,7 +153,19 @@ namespace MoonTools.Core.Graph
|
||||||
|
|
||||||
if (currentNode.Equals(end))
|
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);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -218,7 +218,8 @@ namespace Tests
|
||||||
.And
|
.And
|
||||||
.HaveCount(3);
|
.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>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -248,7 +248,8 @@ namespace Tests
|
||||||
.And
|
.And
|
||||||
.HaveCount(3);
|
.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>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue