【问题标题】:Write 100'000 rows in xml file with Xdocument take too long time使用 Xdocument 在 xml 文件中写入 100'000 行需要太长时间
【发布时间】:2014-07-23 07:36:52
【问题描述】:

我尝试在已经存在的 xml 文件中添加行节点,并在其中添加平均 (100'000 行)。 一切正常,但它真的很慢..我不知道为什么。我必须停止我的程序,因为它已经 10 分钟了,还没有完成^^。

我使用 Xdocument 类添加节点和 XmlTextWriter 因为我需要搜索具有属性的后代节点(区域)并在添加节点之后。

非常感谢

这是我的 xmlFile

<World>
  <Matrix>
    <Regions>
      <Region id="0" min="x:0;y:0;z:0" max="x:256;y:16;z:256">
        <Structures type="cube" >
        </Structures>
      </Region>
      <Region id="1" min="x:256;y:0;z:0" max="x:512;y:16;z:256">
        <Structures type="cube" >
        </Structures>
      </Region>
      <Region id="2" min="x:512;y:0;z:0" max="x:768;y:16;z:256">
        <Structures type="cube" >
        </Structures>
      </Region>
      // till Region id="512" ...

以及我用来插入新节点的代码

更新:使用 StringBuilder 提高内存使用率 像 @threeFx 一样给我建议

// Loop 100'000 times in a recursive method ...

// Search the good node
var reg = arcadia.xDocumentWorld.Descendants("Region").FirstOrDefault(s => s.Attribute("id").Value == region.Index.ToString());
var struc = reg.Element("Structures");
//string posMin = "x:"+ node_.CubeNode.BoundingBox.Min.X+";y:"+ node_.CubeNode.BoundingBox.Min.Y+"z:"+ node_.CubeNode.BoundingBox.Min.Z;
//string posMax = "x:"+ node_.CubeNode.BoundingBox.Max.X+";y:"+ node_.CubeNode.BoundingBox.Max.Y+"z:"+ node_.CubeNode.BoundingBox.Max.Z;

var sbMin = new StringBuilder();
var sbMax = new StringBuilder();

sbMin.Append("x:");
sbMin.Append(node_.CubeNode.BoundingBox.Min.X);
sbMin.Append("y:");
sbMin.Append(node_.CubeNode.BoundingBox.Min.Y);
sbMin.Append("z:");
sbMin.Append(node_.CubeNode.BoundingBox.Min.Z);

sbMax.Append("x:");
sbMax.Append(node_.CubeNode.BoundingBox.Max.X);
sbMax.Append("y:");
sbMax.Append(node_.CubeNode.BoundingBox.Max.Y);
sbMax.Append("z:");
sbMax.Append(node_.CubeNode.BoundingBox.Max.Z);

var cube = new XElement("Cube", new XAttribute("id", node_.ItemGroup),
                                new XAttribute("min", sbMin.ToString()),
                                new XAttribute("max", sbMax.ToString()));

//Add the new cube node
struc.Add(cube);

//Dispose the StringBuilder
sbMin.Clear();
sbMax.Clear();

正如我现在通过测试分析性能看到的那样,.Net Linq [List.FirstOrDefault] 花费了很多性能..

var reg = arcadia.xDocumentWorld.Descendants("Region").FirstOrDefault(s => s.Attribute("id").Value == region.Index.ToString());

【问题讨论】:

  • 缩小范围:您是否尝试过分析(使用较小的数据集)您的程序以查看热点在哪里?
  • 我刚刚完成了一个基本的性能测试并放了一张图片。我现在打算用 CLR Profiler 做另一个测试来检查内存 GC。

标签: c# .net xml linq-to-xml


【解决方案1】:

使用+ 连接字符串真的效率很低,因为每次使用+ 都会创建一个新实例。如果你使用StringBuilder 来连接字符串,你会更好:

StringBuilder sb = new StringBuilder();

sb.Append("x:");
sb.Append(node_.CubeNode.BoundingBox.Mix.X);
sb.Append("y:");
sb.Append(node_.CubeNode.BoundingBox.Min.Y);
sb.Append("z:");
sb.Append(node_.CubeNode.BoundingBox.Mix.Z);

string posMin = sb.ToString();

sb.Clear();

// do the same for posMax    

【讨论】:

  • 谢谢你的回答^^你是对的,.我现在更改我的代码并更新我的描述。但结果还是一样的,只是可能使用 stringbuilder instand string 提高内存使用率。当我想构建它时,构建我的 xml 文件仍然很慢。你知道为什么吗?
  • @MehdiBugnard 该方法是否必须是递归的? C# 中的递归方法通常比迭代循环慢(有例外),因为 C# 不支持 Tail call optimisation
  • 是的,这段代码在递归方法中,但如果我运行这段代码而不尝试写入 xml 文件,这真的很快(9-10 秒)。所以这意味着,它很慢,因为我尝试以递归方法写入 xml 文件?
  • @MehdiBugnard 可能最昂贵的部分是实际的写作而不是递归。
  • 我会在构建 XML 时构建一个单独的 Dictionary 并使用它来查找适当的区域节点,而不是通过 FirstOrDefault() 搜索 Xml 树。这将从根本上提高您的表现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-18
  • 1970-01-01
  • 1970-01-01
  • 2014-12-15
  • 1970-01-01
  • 2011-01-12
  • 2014-01-23
相关资源
最近更新 更多