C#如何有效地池化节点树的对象?

时间:2015-04-25 00:49:31

标签: c# reference mono dispose pool

我有一个节点类,它只包含值类型属性和一个引用类型:它的父节点。执行树搜索时,这些节点会在很短的时间内创建并销毁数十万次。

public class Node
{
   public Node Parent { get; set; }
   public int A { get; set; }
   public int B { get; set; }
   public int C { get; set; }
   public int D { get; set; }
}

树搜索看起来像这样:

public static Node GetDepthFirstBest(this ITree tree, Node root)
{
   Node bestNode = root;
   float bestScore = tree.Evaluate(root);

   var stack = new Stack<Node>();
   stack.Push(root);

   while(stack.Count > 0)
   {
      var current = stack.Pop();

      float score = tree.Evaluate(current);
      if (score > bestScore)
      {
         bestNode = current;
         bestScore = score;
      }

      var children = tree.GetChildren(current);
      foreach(var c in children) { stack.Push(c); } 
   }

   return bestNode;
}

因为这是在具有非常旧的GC的Mono运行时中完成的,所以我想尝试汇集节点对象。但是,我对如何知道节点对象何时安全返回池感到茫然,因为仍在使用的其他节点可能会将其作为父节点引用。在搜索结束时,返回最佳节点,并通过返回其祖先形成节点列表。我完全可以控制如何在树中创建节点,如果这有用的话。

我可以尝试和实施哪些选项?

2 个答案:

答案 0 :(得分:0)

所以,幸运的是,如果您正在进行深度优先搜索,这看起来很简单。无论何时到达叶节点,都有两种可能:叶节点是当前最深树的一部分,或者不是。

如果不是,那意味着将此节点返回池是安全的。如果是,那意味着我们可以将旧树中的任何节点返回到我们的池中,这些节点不在我们自己的祖先链中。

现在,如果我们不是一个叶子节点,我们不知道在我们检查完孩子之前我们是否可以被释放。然后,一旦我们所有的孩子都接受了检查,我们就会发现我们的孩子是否认为他们是目前最好的孩子。如果是这样,我们保持自己

这确实意味着我们正在做更多的检查。

这是一些sudo代码:

List bestNodes;

bool evalNode(node, score)
{
    if (childCount == 0)
    {
        if (score > bestScore)
        {
            bestScore = score;
            bestNode = node;
            bestNodes.Add(node);

            return true;
        }
        else
        {
            freeNode(this);

            return false;
        }
    }
    else
    {
        bool inLongest = false;
        foreach (child in children)
        {
            inLongest = evalNode(child, score + 1) || inLongest;
        }

        if (!inLongest)
        {
            freeNode(node);
        }
        else
        {
            free(bestNodes[score]);
            bestNodes[score] = node;
        }             

        return inLongest;
    }
}

答案 1 :(得分:-1)

如果您的节点是结构,请尝试使用ref关键字,这样可以避免每次将节点传递给函数时复制节点。

因此:

struct Node
{
      object obj;
      Node children;
}

public void DoStuffWithNode(ref Node pNode){...Logic...}