Im making an evolutionary algorithm and I have some problems with memory leaks. Basically I have a population consisting of trees. When I perform my crossover operation between two trees I want to swap two sub-trees between the two trees. The problem is that this preocess leaks a lot of memory which results in my program being useless for over 30-40 generations. The most important code is as follows:
The class for nodes:
[System.Serializable]
public class TreeNode
{
ArrayList mChildren = new ArrayList();
TreeNode mParent;
public static TreeNode DeepClone<TreeNode>(TreeNode obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (TreeNode) formatter.Deserialize(ms);
}
}
public TreeNode (TreeNode parent)
{
mParent = parent;
}
}
The class for the trees:
[System.Serializable]
public class Tree
{
TreeNode mRoot = new TreeNode(null);
public static Tree DeepClone<Tree>(Tree obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (Tree) formatter.Deserialize(ms);
}
}
}
I've been looking at How do you do a deep copy of an object in .NET (C# specifically)? for the deep copying, but Im not sure if its implemented correctly.
As for my test program:
for (int i = 0; i < 50; i++)
{
trees[i] = new Tree();
trees[i].generateTree(30);
}
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 49; j++)
{
trees[j].getRandomSubtree(Tree.DeepClone<Tree>(trees[j+1]));
}
System.GC.Collect();
}
The getRandomSubtree() function basically selects a random sub-tree from one tree and swaps it with a randomly selected sub-tree from another tree. I also make sure to update the parent reference of the sub-trees. When I run this code my program is leaking a lot of memory. If I stop making deep copys the program stops leaking memory so something is going on that I quite dont understand.
I don't think you want to serialize the parent field. Mark it as NonSerialized
. Of course, you then need to fix this after deserialization.
Or simply set it to null
before serializing:
public static TreeNode DeepClone<TreeNode>(TreeNode obj)
{
TreeNode oldParent = obj.mParent;
obj.mParent = null;
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
obj.mParent = oldParent;
ms.Position = 0;
TreeNode result = (TreeNode) formatter.Deserialize(ms);
result.mParent = oldParent;
return result;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.