C#处理大XML时Encoding.UTF8.GetString性能过差如何优化
性能问题根源分析
- 冗余的序列化转换流程:将
XmlDocument转内存流、再转全量字符串、最后按行拆分为数组的操作,会针对10万行级的全量数据产生多份冗余拷贝,内存占用和CPU开销极高。 - 过滤逻辑存在严重算法缺陷:你写的循环中每次都执行
lines = lines.Where(o => !o.Contains("rootTemp")).ToArray(),每循环一次就遍历一次全量数组并生成新数组,时间复杂度达到O(n²),这是总耗时高达30分钟的核心原因。 - 最终拼接字符串再加载回
XmlDocument的流程,又额外增加了一次全量数据遍历和拷贝开销。
优化方案
方案1:最小改动修复原有逻辑(仅改几行代码即可达到秒级处理速度)
直接删掉无效的循环过滤逻辑,一次完成拆分+过滤即可,优化后代码如下:
XmlDocument xmlDoc = (XmlDocument)myReportOrginal.Clone(); // 省略冗余的MemoryStream中转,直接获取XML字符串 string xmlContent = xmlDoc.OuterXml; // 一次完成拆分+过滤,无需循环 List<string> lines = xmlContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries) .Where(o => !o.Contains("rootTemp")) .ToList(); // 替换首行XML声明 if (lines.Count > 0) { lines[0] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; } TempXmlOutputResult = new XmlDocument(); TempXmlOutputResult.LoadXml(string.Join(Environment.NewLine, lines));
方案2:直接操作XML DOM(性能最优,10万行级数据处理耗时低于1秒)
你需要实现的修改逻辑完全不需要转成字符串数组处理,直接操作XmlDocument的DOM节点即可,全程无冗余序列化/拆分/拼接开销,代码如下:
XmlDocument xmlDoc = (XmlDocument)myReportOrginal.Clone(); // 等价于修改首行XML声明 XmlDeclaration declaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null); if (xmlDoc.FirstChild is XmlDeclaration oldDeclare) { xmlDoc.ReplaceChild(declaration, oldDeclare); } else { xmlDoc.InsertBefore(declaration, xmlDoc.DocumentElement); } // 等价于删除所有带rootTemp的行 XmlNodeList rootTempNodes = xmlDoc.GetElementsByTagName("rootTemp"); // 倒序删除避免集合索引错乱 for (int i = rootTempNodes.Count - 1; i >= 0; i--) { rootTempNodes[i].ParentNode.RemoveChild(rootTempNodes[i]); } // 直接赋值无需重新加载 TempXmlOutputResult = xmlDoc;
内容的提问来源于stack exchange,提问作者zawier
相关产品推荐
相关产品推荐

