当前位置: 首页 > 知识库问答 >
问题:

`系统。Xml。Linq`消耗大量内存

陶智
2023-03-14

似乎是系统。Xml。Linq正在消耗大量内存,即使在应该释放任何资源之后也是如此。简单的演示

await using ( System.IO.FileStream stream = new ( xmlFilePath, System.IO.FileMode.Open) ) {
    using ( System.Xml.XmlReader reader = System.Xml.XmlReader.Create( stream, new () { ConformanceLevel = System.Xml.ConformanceLevel.Fragment, Async = true } ) ) {
        int i = 0;
        while ( await reader.ReadAsync().ConfigureAwait( false ) ) {
            while ( reader.NodeType != System.Xml.XmlNodeType.None ) {
                if ( reader.NodeType == System.Xml.XmlNodeType.XmlDeclaration ) {
                    await reader.SkipAsync().ConfigureAwait( false );
                    continue;
                }
                if ( ct.IsCancellationRequested ) {
                    continue;
                }
                i++;
                if ( i % 100000 == 0 ) {
                    Console.WriteLine( $"Processed {i}: {reader.ReadString()}" );
                }
                System.Xml.Linq.XNode node = await System.Xml.Linq.XNode.ReadFromAsync( reader, ct ).ConfigureAwait( false );

            }
        }
    }
}
Console.WriteLine( $"\n---->Memory Use/false: {GC.GetTotalMemory(false):N0}");
Console.WriteLine( $"---->Memory Use      : {GC.GetTotalMemory(true):N0}\n");
return;

产出:

---->Memory Use/false: 402,639,448
---->Memory Use      : 400,967,152

如果替换XNode部分,

                        string xmlFilePath = "/home/eric/dev/src/github.com/erichiller/mkmrk-dotnet/src/Cli/dataset/cme/definition/2021/11/2021-11-05/20211104.061134-05_20211104.030927-05_cmeg.nymex.fut.prf.xml";
                        
await using ( System.IO.FileStream stream = new ( xmlFilePath, System.IO.FileMode.Open) ) {
    using ( System.Xml.XmlReader reader = System.Xml.XmlReader.Create( stream, new () { ConformanceLevel = System.Xml.ConformanceLevel.Fragment, Async = true } ) ) {
        int i = 0;
        while ( await reader.ReadAsync().ConfigureAwait( false ) ) {
            while ( reader.NodeType != System.Xml.XmlNodeType.None ) {
                if ( reader.NodeType == System.Xml.XmlNodeType.XmlDeclaration ) {
                    await reader.SkipAsync().ConfigureAwait( false );
                    continue;
                }
                if ( ct.IsCancellationRequested ) {
                    continue;
                }
                i++;
                if ( i % 100000 == 0 ) {
                    Console.WriteLine( $"Processed {i}: {reader.ReadString()}" );
                }
                await reader.ReadAsync().ConfigureAwait( false );
            }
        }
    }
}
Console.WriteLine( $"\n---->Memory Use/false: {GC.GetTotalMemory(false):N0}");
Console.WriteLine( $"---->Memory Use      : {GC.GetTotalMemory(true):N0}\n");
return;

使用率大幅下降:

---->Memory Use/false: 11,048,992
---->Memory Use      : 6,317,248

我在这里误解了什么/做错了什么?正在加载的文件很大(~60MB),但即使XNode需要使用那么多内存,也不应该在时间控制台之前释放它。是否已到达写入线

共有1个答案

翟誉
2023-03-14

LINQtoXML急切地将整个XML文档加载到内存中,创建许多对象来表示它。在读取时,您似乎在循环中执行了很多次,但没有对递归遍历进行太多保护。

但是,使用允许手动控制的XmlReader,它只能读取足够的信息,并允许消费者决定如何使用它。

当块被关闭时,内存并不总是被释放。堆上的东西会在某个时候被气相色谱清理掉。

 类似资料:
  • 问题内容: 该表包含大约一千万行。 这会导致内存使用量稳定增加到4 GB左右,这时行将快速打印。第一行打印之前漫长的延迟使我感到惊讶–我希望它几乎可以立即打印。 我也尝试过以相同的方式表现。 我不知道Django将什么加载到内存中或为什么这样做。我希望Django在数据库级别遍历结果,这意味着结果将以大致恒定的速率打印(而不是经过漫长的等待一次全部打印)。 我误会了什么? (我不知道它是否相关,但

  • 当我刚接触drools时,我浏览了一些论坛,开发了一个使用KnowledgeBuilder api和StatefulKnowledgeSessions配置drools的应用程序。当时drools文件的数量较少,并且与应用程序打包在一起。分析时,我发现drools消耗了大量内存,内存分配率(TLAB)很高。这让我思考,是否需要有一个缓存解决方案,以避免每次有应用程序请求时都创建KnowledgeSe

  • 我在Azure上的Ubuntu 16.04.4 LTS实例上运行了一些docker swarm容器。容器运行Java Spring Boot和Netflix OSS应用程序,如Eureka、Ribbon、Gateway等应用程序。我发现我的容器占用了巨大的内存,尽管服务只是RESTendpoint。 我试图通过传递Java VM参数来限制内存消耗,如下所示,但这并没有帮助,大小甚至没有改变。 请在

  • 我正在尝试使用Cooja模拟器模拟无线传感器网络。我想观察RPL协议在Contiki-OS中消耗的内存量。我使用sky-mote进行模拟,并创建了一个包含许多它们的网络。有没有什么方法可以观察RPL协议为保留邻居和路由表而消耗的内存量?

  • 在过去的几周里,我们一直在关注这个问题。 每隔几天,我们compose.ioMongo数据库的连接数就会飙升至近5000,这是连接限制。似乎没有任何特定的触发此行为。 日志如下所示: Compose支持告诉我们,这几乎肯定是MongoDB驱动程序的问题,我们应该使用连池。我们需要实现Meteor连接池的一些配置吗?

  • 我们希望单独写每个列表,也以前写的文件不应该加载到堆,而写下一个列表。