【问题标题】:How to speed up tree creation如何加快树的创建
【发布时间】:2015-06-23 14:46:15
【问题描述】:

我有这个代码来生成一个临时树,其代码如下

object regionSale = regionValue.GetValueAsString();

if (root.Children.Count > 0)
{
    if ((tmpNode.Data.Level) == (levelNested - 1))
    {
        var newChild = new Node
        {
            Data = new NodeData
                    {
                        Level = levelNested,
                        RegionName = elemNested.GetValueAsString(),
                        RegionValue = NAValue.Equals(regionSale.ToString())
                            ? null
                            : (double?)regionValue.GetValueAsFloat64()
                    },
            Parent = tmpNode
        };

        tmpNode.Children.Add(newChild);
        tmpNode = newChild;

    }
    else if (tmpNode.Data.Level == levelNested)
    {
        var node = tmpNode.Parent;
        var newChild = new Node
        {
            Data = new NodeData
                    {
                        Level = levelNested,
                        RegionName = elemNested.GetValueAsString(),
                        RegionValue = NAValue.Equals(regionSale.ToString())
                            ? null
                            : (double?)regionValue.GetValueAsFloat64()
                    },
            Parent = node
        };

        node.Children.Add(newChild);
        tmpNode = newChild;
    }
    else
    {
        var parentNode = tmpNode.Parent;
        while ((parentNode.Data.Level) != (levelNested - 1))
        {
            parentNode = parentNode.Parent;
        }
        var newChild = new Node
        {
            Data = new NodeData
                    {
                        Level = levelNested,
                        RegionName = elemNested.GetValueAsString(),
                        RegionValue = NAValue.Equals(regionSale.ToString())
                            ? null
                            : (double?)regionValue.GetValueAsFloat64()
                    },
            Parent = parentNode
        };

        parentNode.Children.Add(newChild);
        tmpNode = newChild;
    }
}
else
{
    var children = new Node();
    children.Data = new NodeData
    {
        Level = levelNested,
        RegionName = elemNested.GetValueAsString(),
        RegionValue = NAValue.Equals(regionSale.ToString())
            ? null
            : (double?)regionValue.GetValueAsFloat64()
    };

    children.Parent = root;
    root.Children.Add(children);
    tmpNode = children;
}

传递给这个函数的数据是一个根节点,比如:

for (var nestedIndex = 0; nestedIndex < numofBulkValues; nestedIndex++)
{
    var bulkElementNested = refBulkField.GetValueAsElement(nestedIndex);

    var elemNested = bulkElementNested.GetElement(0);
    var levelElement = bulkElementNested.GetElement(1);
    var regionValue = bulkElementNested.GetElement(2);
    var levelNested = levelElement.GetValueAsInt32();

    tmpNode = GenerateTree(root, tmpNode, elemNested, regionValue, levelNested);
}

在这种情况下,我得到的数据是格式

ADSK UW EQUITY  
Europe, Middle East and Africa  Level=1
The Americas  Level=1
   U.S  Level=2
   Other Americas  Level=2
The Asia/Pacific  Level=1
   Other Asia/Pacific  Level=2
   Japan  Level=2
Reconciliation  Level=1

并且有多个这样的股票。问题是这个过程需要很长时间,几乎 9 秒才能完成,但只需要 16 秒即可显示实际结果。是的,这是应用程序的核心,非常重要,因此不能跳过。有什么办法可以减少创建这棵树的时间吗?

我的节点类如下:

public class Node
{
    public Node()
    {

    }
    public Node(Node node)
        : this()
    {
        if (node == null)
            return;
        this.Data = new NodeData(node.Data);
        if (node.Children != null)
            this.Children = new List<Node>(node.Children);
        this.Parent = new Node(node.Parent);
    }
    public NodeData Data;
    public List<Node> Children = new List<Node>();
    public Node Parent;
}
public class NodeData
{
    public NodeData()
    {

    }
    public NodeData(NodeData nodeData)
        : this()
    {
        if (nodeData == null)
            return;
        this.RegionName = nodeData.RegionName;
        this.RegionValue = nodeData.RegionValue;
        this.Level = nodeData.Level;

    }
    public string RegionName;
    public double? RegionValue;
    public int Level;
}

如果我可以提供更多信息,请告诉我。感谢您的帮助

【问题讨论】:

  • Profiler 将帮助您稍微缩小上下文范围(例如,如果!) GetValueAsString() 需要 100 毫秒,那么您就知道必须在哪里寻找。乍一看(没有分析),我看到很多很多 List 操作(和(重新)分配)。如果列表可能大小或多或少知道...您可以从那里开始(创建具有合理初始容量的列表以防止重新分配)。
  • @AdrianoRepetti 嗨,我检查了分析器,它说 GetValueAsString 使用了
  • Getvalueasstring 只是一个例子!计时器?您已经有探查器结果要检查...
  • @AdrianoRepetti 也根本不知道列表大小,因为即使对于相同的股票,它也可能从 1 次执行到下一次执行不同。可以添加或删除许多这样的区域。
  • @AdrianoRepetti 是的.. 但我正在检查数据提取是否是问题或树的生成.. 探查器对此功能没有显示太多。

标签: c# performance tree


【解决方案1】:

好的,

所以我所做的是我在 Node.cs 类中进行了如下更改:

public class Node
{
    public Node()
    {

    }
    public Node(Node node)
        : this()
    {
        if (node == null)
            return;
        if (node.Children != null)
            this.Children = new List<Node>(node.Children);
        this.Parent = new Node(node.Parent);
        this.RegionName = nodeData.RegionName;
        this.RegionValue = nodeData.RegionValue;
        this.Level = nodeData.Level;
    }
    public List<Node> Children = new List<Node>();
    public Node Parent;
    public string RegionName;
    public double? RegionValue;
    public int Level;
}

我还检查了记录日志的函数,所以被大量调用的小函数(for inside for..)我已经删除了这些日志。这一切都将 900 只股票的时间从 4.30 分钟减少到了大约 1.30 分钟。但我想问一下,我是否可以做更多的事情来让它更快。

还有一个问题: 仅对于从数据库(sqlite 数据库)中提取数据的众多函数中的 1 个,connection.Open() 需要大量时间。这个问题可能是因为连接打开了很长时间吗?或者是否有可能已经打开了另一个连接,所以关闭它并启动这个连接需要时间?

【讨论】:

  • Jay,我不想学究气,但是...要知道我们需要做什么来profile您的代码...日志是个大问题?我们甚至没有看到它们......就像这是用玻璃球优化!大声笑
  • 哈哈哈......我同意......分析器将日志显示为主要问题可能是因为 IO 操作......所以被调用大约 100 次的函数具有 3 到 4 条日志行是一个主要问题。 .
  • 即使在分析器中,我越深入了解任何需要时间的函数,它只是说记录器正在使用大量时间......只有一个问题我无法理解。我会更新我给出的答案以包括这个。
猜你喜欢
  • 2017-12-13
  • 1970-01-01
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多