【问题标题】:XmlReader Memory Leak .Net Core 2.0 [duplicate]XmlReader内存泄漏.Net Core 2.0 [重复]
【发布时间】:2018-10-05 03:06:38
【问题描述】:

我有一个 .NET Core 2.0 正在处理超过 30,000 个 XML 文件的列表,并且似乎存在内存泄漏。

现在我的程序所做的只是一次读取一个文件,将文件内容添加到列表中,然后移动到下一个文件。

这些文件没有发生任何事情,但我的程序内存每个文件增加了 0.5 MB。文件本身在 5KB 到 10KB 之间。

这里是处理方法。

public async Task ProcessModelFile<TModel>(List<string> dataFileList) where TModel : InstitutionModel
    {
        foreach (var file in dataFileList)
        {
            var xmlLoadFile = new XmlLoadFile<TModel>();
            xmlLoadFile.AddFile(file, rootElementName: $"ArrayOf{TextService.GetClassNameFromType<TModel>()}");
        }
    }

还有AddFile方法和类:

internal class XmlLoadFile<TModel> where TModel : class
        {

            public List<TModel> ModelList { get; set; }

            internal void AddFile(string file, string rootElementName = "", bool HasHistoricalCutOff = false, DateTime? HistoricalCutOffDate = null)
            {
                using (XmlReader reader = XmlReader.Create(file, new XmlReaderSettings { CheckCharacters = false }))
                {
                    XmlSerializer serializer;

                    if (!string.IsNullOrWhiteSpace(rootElementName))
                    {
                        XmlRootAttribute rootElement = new XmlRootAttribute();
                        rootElement.ElementName = rootElementName;
                        serializer = new XmlSerializer(typeof(List<TModel>), rootElement);
                    }
                    else
                    {
                        serializer = new XmlSerializer(typeof(List<TModel>));
                    }

                    ModelList.AddRange((List<TModel>)serializer.Deserialize(reader));
                }
            }
        }

每次 foreach 循环运行时,我的内存都会增加 0.5MB,而且我拥有的文件数量会迅速超过 15GB。在 VS 中调试并拍摄内存快照并不考虑正在使用的内存。

垃圾收集似乎没有正确释放此内存。

【问题讨论】:

  • 在假设 XmlReader 中存在内存泄漏之前,请检查 您的 代码。生成了多少可以重用的序列化程序? ModelList 有多少次必须重新分配其内部缓冲区,因为它已满? XmlSerializers 被缓存,因此运行时不必在一个已经可用时重建一个只有在使用正确的构造函数时
  • 如果您将它们添加到列表中,那么为什么垃圾收集器会在使用列表时收集它们?
  • @YahyaHussein 将数据存储在数组中。当数组已满时,将创建一个大小为两倍的新数组,并复制旧数据。这将导致 lot 的孤立对象的大小每次翻倍。所有这些都必须在某个时候被垃圾收集。
  • 减少重新分配的一种方法是在创建列表时使用capacity 参数来创建足够大的列表来容纳大部分预期数据。这意味着你必须猜测。另一个想法是使用容量等于文件数量的 List>。处理完成后,将列表展平,例如使用SelectMany()
  • 这个类的调用方式只需要一个序列化器,当你构造XmlLoadFile时,它的根元素已经知道了。不要将该元素作为参数传递给AddFile,而是在XmlLoadFile 的构造函数中创建两个序列化程序并将它们存储在一个字段中:一个有根元素,一个没有

标签: c# asp.net-core-2.0 xmlserializer


【解决方案1】:

XmlSerializer 会被缓存,因此运行时不必在一个已经可用的情况下重新构建一个,但前提是使用了正确的构造函数。

【讨论】:

    猜你喜欢
    • 2023-01-30
    • 1970-01-01
    • 2021-07-19
    • 2013-12-25
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    相关资源
    最近更新 更多