From bdfdc39075009ed7ed9c0149fdb2144ac57bf59d Mon Sep 17 00:00:00 2001 From: smbadiwe Date: Fri, 10 Nov 2017 08:45:27 -0800 Subject: [PATCH] It appears intentionally clearing lists and setting variables to null as soon as they're no more needed has an impact on memory footprint. --- MODA.Impl/ModaAlgorithms.1.cs | 16 ++++----- MODA.Impl/ModaAlgorithms.2.Modified.cs | 25 ++++++++------ MODA.Impl/ModaAlgorithms.2.cs | 20 ++++++++--- MODA.Impl/ModaAlgorithms.3.cs | 10 +++--- MODA.Impl/QueryGraph.cs | 6 ++-- MODA.Impl/Utils.cs | 47 ++++++++++++++++++++++---- ParaMODA/ParaMODA.csproj | 1 + ParaMODA/Program.cs | 4 +-- QuickGraph/Alt/UndirectedGraph.cs | 4 ++- 9 files changed, 92 insertions(+), 41 deletions(-) diff --git a/MODA.Impl/ModaAlgorithms.1.cs b/MODA.Impl/ModaAlgorithms.1.cs index 3f13949..c83c0e7 100644 --- a/MODA.Impl/ModaAlgorithms.1.cs +++ b/MODA.Impl/ModaAlgorithms.1.cs @@ -31,7 +31,7 @@ public static Dictionary Algorithm1_C(UndirectedGraph i { qGraph = GetNextNode()?.QueryGraph; if (qGraph == null) break; - IList mappings; + ICollection mappings; if (qGraph.EdgeCount == (subgraphSize - 1)) // i.e. if qGraph is a tree { var inputGraphClone = inputGraph.Clone(); @@ -98,7 +98,7 @@ public static Dictionary Algorithm1_C(UndirectedGraph i } else { - List mappings; + ICollection mappings; if (UseModifiedGrochow) { // Modified Mapping module - MODA and Grockow & Kellis @@ -127,10 +127,10 @@ public static Dictionary Algorithm1_C(UndirectedGraph i /// /// Frequency value, above which we can comsider the subgraph a "frequent subgraph" /// - public static Dictionary> Algorithm1(UndirectedGraph inputGraph, QueryGraph qGraph, int subgraphSize = -1, int thresholdValue = 0) + public static Dictionary> Algorithm1(UndirectedGraph inputGraph, QueryGraph qGraph, int subgraphSize = -1, int thresholdValue = 0) { // The enumeration module (Algo 3) needs the mappings generated from the previous run(s) - Dictionary> allMappings; + Dictionary> allMappings; int numIterations = -1; if (inputGraph.VertexCount < 121) numIterations = inputGraph.VertexCount; @@ -138,12 +138,12 @@ public static Dictionary> Algorithm1(UndirectedGraph< { #region Use MODA's expansion tree var treatedNodes = new HashSet(); - allMappings = new Dictionary>(_builder.NumberOfQueryGraphs); + allMappings = new Dictionary>(_builder.NumberOfQueryGraphs); do { qGraph = GetNextNode()?.QueryGraph; if (qGraph == null) break; - IList mappings; + ICollection mappings; if (qGraph.IsTree(subgraphSize)) { var inputGraphClone = inputGraph.Clone(); @@ -200,7 +200,7 @@ public static Dictionary> Algorithm1(UndirectedGraph< } else { - List mappings; + ICollection mappings; if (UseModifiedGrochow) { // Modified Mapping module - MODA and Grockow & Kellis @@ -213,7 +213,7 @@ public static Dictionary> Algorithm1(UndirectedGraph< } qGraph.RemoveNonApplicableMappings(mappings, inputGraph); - allMappings = new Dictionary>(1) { { qGraph, mappings } }; + allMappings = new Dictionary>(1) { { qGraph, mappings } }; } return allMappings; diff --git a/MODA.Impl/ModaAlgorithms.2.Modified.cs b/MODA.Impl/ModaAlgorithms.2.Modified.cs index 9af411e..4d34c4b 100644 --- a/MODA.Impl/ModaAlgorithms.2.Modified.cs +++ b/MODA.Impl/ModaAlgorithms.2.Modified.cs @@ -1,13 +1,9 @@ //This is the one that has gone bad using QuickGraph; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; using System.Threading; -using System.Threading.Tasks; namespace MODA.Impl { @@ -25,17 +21,17 @@ public partial class ModaAlgorithms /// H /// G /// To be decided. If not set, we use the size / 3 - private static List Algorithm2_Modified(QueryGraph queryGraph, UndirectedGraph inputGraph, int numberOfSamples, bool getInducedMappingsOnly) + private static ICollection Algorithm2_Modified(QueryGraph queryGraph, UndirectedGraph inputGraph, int numberOfSamples, bool getInducedMappingsOnly) { if (numberOfSamples <= 0) numberOfSamples = inputGraph.VertexCount / 3; - + var theMappings = new Dictionary, List>(MappingNodesComparer); var inputGraphDegSeq = inputGraph.GetNodesSortedByDegree(numberOfSamples); var threadName = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Thread {0}:\tCalling Algo 2-Modified:\n", threadName); - var queryGraphEdges = queryGraph.Edges.ToList(); + var queryGraphEdges = queryGraph.Edges.ToArray(); var h = queryGraph.Vertices.ElementAt(0); var f = new Dictionary(1); for (int i = 0; i < inputGraphDegSeq.Count; i++) @@ -62,18 +58,25 @@ private static List Algorithm2_Modified(QueryGraph queryGraph, Undirect theMappings[item.Key] = item.Value; } } - mappings = null; } + mappings.Clear(); + mappings = null; #endregion } } + f.Clear(); + f = null; + Array.Clear(queryGraphEdges, 0, queryGraphEdges.Length); + queryGraphEdges = null; + inputGraphDegSeq.Clear(); + inputGraphDegSeq = null; var toReturn = new HashSet(theMappings.Values.SelectMany(s => s)); + theMappings.Clear(); theMappings = null; - inputGraphDegSeq = null; - + Console.WriteLine("\nThread {0}:\tAlgorithm 2: All iteration tasks completed. Number of mappings found: {1}.\n", threadName, toReturn.Count); - return toReturn.ToList(); + return toReturn; } } diff --git a/MODA.Impl/ModaAlgorithms.2.cs b/MODA.Impl/ModaAlgorithms.2.cs index 2c54ebb..ba50d19 100644 --- a/MODA.Impl/ModaAlgorithms.2.cs +++ b/MODA.Impl/ModaAlgorithms.2.cs @@ -13,7 +13,7 @@ public partial class ModaAlgorithms /// H /// G /// To be decided. If not set, we use the size / 3 - internal static List Algorithm2(QueryGraph queryGraph, UndirectedGraph inputGraphClone, int numberOfSamples, bool getInducedMappingsOnly) + internal static ICollection Algorithm2(QueryGraph queryGraph, UndirectedGraph inputGraphClone, int numberOfSamples, bool getInducedMappingsOnly) { if (numberOfSamples <= 0) numberOfSamples = inputGraphClone.VertexCount / 3; @@ -22,7 +22,7 @@ internal static List Algorithm2(QueryGraph queryGraph, UndirectedGraph< var theMappings = new Dictionary, List>(MappingNodesComparer); var inputGraphDegSeq = inputGraphClone.GetNodesSortedByDegree(numberOfSamples); var queryGraphVertices = queryGraph.Vertices.ToArray(); - var queryGraphEdges = queryGraph.Edges.ToList(); + var queryGraphEdges = queryGraph.Edges.ToArray(); var subgraphSize = queryGraphVertices.Length; var threadName = System.Threading.Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Thread {0}:\tCallingu Algo 2:\n", threadName); @@ -39,7 +39,8 @@ internal static List Algorithm2(QueryGraph queryGraph, UndirectedGraph< var f = new Dictionary(1); f[h] = g; var mappings = Utils.IsomorphicExtension(f, queryGraph, queryGraphEdges, inputGraphClone, getInducedMappingsOnly); - + f.Clear(); + f = null; if (mappings.Count > 0) { foreach (var item in mappings) @@ -56,6 +57,8 @@ internal static List Algorithm2(QueryGraph queryGraph, UndirectedGraph< } } } + mappings.Clear(); + mappings = null; #endregion } } @@ -63,10 +66,17 @@ internal static List Algorithm2(QueryGraph queryGraph, UndirectedGraph< //Remove g inputGraphClone.RemoveVertex(g); } + Array.Clear(queryGraphEdges, 0, queryGraphEdges.Length); + queryGraphEdges = null; + inputGraphDegSeq.Clear(); + inputGraphDegSeq = null; + var toReturn = new HashSet(theMappings.Values.SelectMany(s => s)); - + theMappings.Clear(); + theMappings = null; + Console.WriteLine("Thread {0}:\tAlgorithm 2: All tasks completed. Number of mappings found: {1}.", threadName, toReturn.Count); - return toReturn.ToList(); + return toReturn; } } } diff --git a/MODA.Impl/ModaAlgorithms.3.cs b/MODA.Impl/ModaAlgorithms.3.cs index 2fcd1f1..b07dbb8 100644 --- a/MODA.Impl/ModaAlgorithms.3.cs +++ b/MODA.Impl/ModaAlgorithms.3.cs @@ -18,12 +18,12 @@ public partial class ModaAlgorithms /// /// /// NB: This param is still used even outside this method is call. So, be careful how you set/clear its values. - private static IList Algorithm3(Dictionary> allMappings, UndirectedGraph inputGraph, QueryGraph queryGraph, + private static IList Algorithm3(Dictionary> allMappings, UndirectedGraph inputGraph, QueryGraph queryGraph, AdjacencyGraph expansionTree, QueryGraph parentQueryGraph, out string newFileName, string fileName = null) { newFileName = null; - IList parentGraphMappings; + ICollection parentGraphMappings; if (string.IsNullOrWhiteSpace(fileName)) { if (!allMappings.TryGetValue(parentQueryGraph, out parentGraphMappings)) @@ -53,7 +53,7 @@ private static IList Algorithm3(Dictionary> var list = new List(); int oldCount = parentGraphMappings.Count, id = 0, queryGraphEdgeCount = queryGraph.EdgeCount; - var queryGraphEdges = queryGraph.Edges.ToList(); + var queryGraphEdges = queryGraph.Edges.ToArray(); var groupByGNodes = parentGraphMappings.GroupBy(x => x.Function.Values, MappingNodesComparer); //.ToDictionary(x => x.Key, x => x.ToArray(), MappingNodesComparer); foreach (var set in groupByGNodes) @@ -87,7 +87,7 @@ private static IList Algorithm3(Dictionary> } } } - + queryGraphEdges = null; var threadName = System.Threading.Thread.CurrentThread.ManagedThreadId; // Remove mappings from the parent qGraph that are found in this qGraph @@ -99,7 +99,7 @@ private static IList Algorithm3(Dictionary> { parentGraphMappings.Add(item); } - + theRest = null; // Now, remove duplicates queryGraph.RemoveNonApplicableMappings(list, inputGraph); if (!string.IsNullOrWhiteSpace(fileName) && oldCount > parentGraphMappings.Count) diff --git a/MODA.Impl/QueryGraph.cs b/MODA.Impl/QueryGraph.cs index 5bf0320..a5eedb3 100644 --- a/MODA.Impl/QueryGraph.cs +++ b/MODA.Impl/QueryGraph.cs @@ -47,14 +47,14 @@ public IList ReadMappingsFromFile(string filename) /// /// /// filename where it is written - public string WriteMappingsToFile(IList mappings) + public string WriteMappingsToFile(ICollection mappings) { var fileName = $"{mappings.Count}#{Identifier}.ser"; System.IO.File.WriteAllText(fileName, Extensions.CompressString(Newtonsoft.Json.JsonConvert.SerializeObject(mappings))); return fileName; } - public void RemoveNonApplicableMappings(IList mappings, UndirectedGraph inputGraph) + public void RemoveNonApplicableMappings(ICollection mappings, UndirectedGraph inputGraph) { if (mappings.Count == 0) return; @@ -62,7 +62,7 @@ public void RemoveNonApplicableMappings(IList mappings, UndirectedGraph var mapGroups = mappings.GroupBy(x => x.Function.Values, ModaAlgorithms.MappingNodesComparer); //.ToDictionary(x => x.Key, x => x.ToArray()); var toAdd = new List(); - var queryGraphEdges = Edges.ToList(); + var queryGraphEdges = Edges.ToArray(); foreach (var group in mapGroups) { var g_nodes = group.Key; // Remember, f(h) = g, so .Values is for g's diff --git a/MODA.Impl/Utils.cs b/MODA.Impl/Utils.cs index 050c792..84f04b0 100644 --- a/MODA.Impl/Utils.cs +++ b/MODA.Impl/Utils.cs @@ -20,14 +20,14 @@ public class Utils /// /// true if [is mapping correct] [the specified function]; otherwise, false. /// - internal static MappingTestResult IsMappingCorrect(SortedList function, List> queryGraphEdges, UndirectedGraph inputGraph, bool checkInducedMappingOnly, int subGraphEdgeCount = 0) + internal static MappingTestResult IsMappingCorrect(SortedList function, Edge[] queryGraphEdges, UndirectedGraph inputGraph, bool checkInducedMappingOnly, int subGraphEdgeCount = 0) { var subgraph = GetSubgraph(inputGraph, function.Values); - + return IsMappingCorrect2(function, subgraph, queryGraphEdges, checkInducedMappingOnly); } - internal static MappingTestResult IsMappingCorrect2(SortedList function, UndirectedGraph subgraph, List> queryGraphEdges, bool checkInducedMappingOnly) + internal static MappingTestResult IsMappingCorrect2(SortedList function, UndirectedGraph subgraph, Edge[] queryGraphEdges, bool checkInducedMappingOnly) { // Gather the corresponding potential images of the parentQueryGraphEdges in the input graph var edgeImages = new HashSet>(); @@ -41,6 +41,8 @@ internal static MappingTestResult IsMappingCorrect2(SortedList functio var compareEdgeCount = result.SubgraphEdgeCount.CompareTo(edgeImages.Count); if (compareEdgeCount < 0) { + edgeImages.Clear(); + edgeImages = null; return result; } @@ -57,10 +59,16 @@ internal static MappingTestResult IsMappingCorrect2(SortedList functio { if (subgraphDegrees[i] != testGdeg[i]) { + edgeImages.Clear(); + edgeImages = null; result.IsCorrectMapping = false; return result; } } + subgraphDegrees.Clear(); + subgraphDegrees = null; + edgeImages.Clear(); + edgeImages = null; result.IsCorrectMapping = true; return result; } @@ -69,6 +77,10 @@ internal static MappingTestResult IsMappingCorrect2(SortedList functio { if (checkInducedMappingOnly) { + subgraphDegrees.Clear(); + subgraphDegrees = null; + edgeImages.Clear(); + edgeImages = null; result.IsCorrectMapping = false; return result; } @@ -77,10 +89,16 @@ internal static MappingTestResult IsMappingCorrect2(SortedList functio { if (subgraphDegrees[i] < testGdeg[i]) // base should have at least the same value as test { + edgeImages.Clear(); + edgeImages = null; result.IsCorrectMapping = false; return result; } } + subgraphDegrees.Clear(); + subgraphDegrees = null; + edgeImages.Clear(); + edgeImages = null; result.IsCorrectMapping = true; return result; } @@ -108,6 +126,8 @@ internal static UndirectedGraph GetSubgraph(UndirectedGraph inputGraph } var subgraph = new UndirectedGraph(); subgraph.AddVerticesAndEdgeRange(inducedSubGraphEdges); + inducedSubGraphEdges.Clear(); + inducedSubGraphEdges = null; return subgraph; } @@ -123,7 +143,7 @@ internal static UndirectedGraph GetSubgraph(UndirectedGraph inputGraph /// If true, then the querygraph must match exactly to the input subgraph. In other words, only induced subgraphs will be returned /// List of isomorphisms. Remember, Key is h, Value is g internal static Dictionary, List> IsomorphicExtension(Dictionary partialMap, QueryGraph queryGraph - , List> queryGraphEdges, UndirectedGraph inputGraph, bool getInducedMappingsOnly) + , Edge[] queryGraphEdges, UndirectedGraph inputGraph, bool getInducedMappingsOnly) { if (partialMap.Count == queryGraph.VertexCount) { @@ -170,6 +190,8 @@ internal static Dictionary, List> IsomorphicExtension(Dictio } newPartialMap[m] = neighbourRange[i]; var subList = IsomorphicExtension(newPartialMap, queryGraph, queryGraphEdges, inputGraph, getInducedMappingsOnly); + newPartialMap.Clear(); + newPartialMap = null; if (subList != null && subList.Count > 0) { foreach (var item in subList) @@ -184,9 +206,15 @@ internal static Dictionary, List> IsomorphicExtension(Dictio listOfIsomorphisms[item.Key] = item.Value; } } + subList.Clear(); + subList = null; } } } + + neighborsOfM = null; // DO NOT Clear this variable + neighbourRange.Clear(); + neighbourRange = null; return listOfIsomorphisms; } @@ -227,6 +255,7 @@ internal static bool IsNeighbourIncompatible(UndirectedGraph inputGraph, } if (!neighboursOfN.Contains(val)) { + neighboursOfN = null; return true; } } @@ -238,14 +267,17 @@ internal static bool IsNeighbourIncompatible(UndirectedGraph inputGraph, { if (!partialMap.TryGetValue(d, out val)) { + neighboursOfN = null; return false; } if (neighboursOfN.Contains(val)) { + neighboursOfN = null; return true; } } } + neighboursOfN = null; return false; } @@ -275,10 +307,10 @@ internal static List ChooseNeighboursOfRange(IEnumerable usedRange, Un } else { - return toReturn; + break; } } - + usedRangeSet = null; return toReturn; } @@ -311,7 +343,10 @@ internal static int GetMostConstrainedNeighbour(IEnumerable domain, Undirec } } } + local = null; // DO NOT clear } + domainDict.Clear(); + domainDict = null; return -1; } diff --git a/ParaMODA/ParaMODA.csproj b/ParaMODA/ParaMODA.csproj index 099e0d2..d92bc13 100644 --- a/ParaMODA/ParaMODA.csproj +++ b/ParaMODA/ParaMODA.csproj @@ -45,6 +45,7 @@ TRACE prompt 4 + false diff --git a/ParaMODA/Program.cs b/ParaMODA/Program.cs index 7cbb0f9..5984041 100644 --- a/ParaMODA/Program.cs +++ b/ParaMODA/Program.cs @@ -9,8 +9,8 @@ static void Main(string[] args) { #if DEBUG string argsStr = ""; - //argsStr = @"runall -g ..\Release\Inputs\SampleInputGraph.txt -n 5"; // -k uses expansion tree - argsStr = @"runall -g ..\Release\Inputs\Ecoli20141001CR_idx.txt -n 4 -k"; // -k uses expansion tree + argsStr = @"runall -g ..\Release\Inputs\SampleInputGraph.txt -n 5 -k"; // -k uses expansion tree + //argsStr = @"runall -g ..\Release\Inputs\Ecoli20141001CR_idx.txt -n 5 -k"; // -k uses expansion tree //argsStr = @"runone -g ..\Release\Inputs\SampleInputGraph.txt -h ..\Release\QueryGraphs\4\qg-5a.txt -n 4 -k"; args = argsStr.Split(' '); Console.WriteLine("args = {0}", string.Join(" ", args)); diff --git a/QuickGraph/Alt/UndirectedGraph.cs b/QuickGraph/Alt/UndirectedGraph.cs index 7d7ca34..6659d07 100644 --- a/QuickGraph/Alt/UndirectedGraph.cs +++ b/QuickGraph/Alt/UndirectedGraph.cs @@ -85,12 +85,13 @@ public IList GetNodesSortedByDegree(int count) } var listToReturn = new List(count); - foreach (var item in tempList.OrderBy(x => x.Value)) + foreach (var item in tempList.OrderByDescending(x => x.Value)) { listToReturn.Add(item.Key); } tempList.Clear(); + tempList = null; return listToReturn; } @@ -149,6 +150,7 @@ public void ClearAdjacentEdges(TVertex v) } } ends.Clear(); + ends = null; } public bool TryGetEdge(TVertex source, TVertex target, out Edge edge)