【问题标题】:Memory not releasing .Net Application内存未释放 .Net 应用程序
【发布时间】:2020-05-12 11:41:31
【问题描述】:

我有一个对象列表。列表中的对象数约为 5,06,011。

它在内存中消耗 190MB。

过了一段时间我就不需要那个列表了。我清除了列表

list.clear() 命令清除该列表中的所有对象。

但是,我的应用程序仍然消耗 190 MB 内存。

如何正确处理列表?

public class FileProperty
    {
        public string Name { get; set; }
        public string DirectoryPath { get; set; }
        public long LastWriteTime { get; set; }
        public long Size { get; set; }
    }

void Main()
{
   var Sqlite = new SqliteConnection(@"Filename=D:\Work\UserData.db");
   var FileProps=Sqlite.Query<FileProperty>("SELECT *FROM FileProperties;").ToList();

   //Task completed with that collection
   //Now want to free memory
   FileProps.Clear();
   //But memory not freed
}

【问题讨论】:

  • 您是如何检查的(哪个工具;哪个指标)?您等待 GC 发生多长时间?列表本身只使用很少的 RAM。这些对象是否被其他东西引用?最好使用 .NET 内存分析器,例如 dotMemory(Resharper 的一部分)。
  • 度量部分非常重要,因为.NET 不会将内存还给操作系统。所以这取决于角度:从操作系统的角度来看,内存已经消失(它已经给了.NET)。从 .NET 的角度来看,内存是空的(里面没有对象)。
  • 我等了 5 分钟。有没有办法强制垃圾收集器释放资源。
  • 添加了小代码@ThomasWeller
  • 您是在运行调试版本还是发布版本?

标签: c# .net .net-core garbage-collection


【解决方案1】:

list.Clear() 不会重置已分配列表的容量。即使在调用 Clear() 之后,容量仍然和以前一样,这意味着底层数组还没有被销毁。

在 Clear() 之后调用 TrimExcess() 将重置最终可能释放内存的容量。

但是,一旦对象没有被任何其他数据结构引用,它应该默认符合垃圾回收的条件。

【讨论】:

  • 同样的问题,在 TrimExcess() 之后也没有释放内存。在任务管理器和 VS 诊断工具中观察应用程序消耗的内存大小
  • 一个由 20.000 个指向对象的指针组成的数组只有 ~400kB,而不是 20MB。
  • @Varun:任务管理器是测量内存的最差工具之一。您在任务管理器中寻找什么内存?您需要了解“工作集”的含义。在> 90%的情况下,工作集不是正确的。事实上,这从来都不是我生命中的最后 13 年。
  • @ThomasWeller 尝试使用数据库中的不同表 列表中的 5,06,011 个对象引用消耗大约 195 兆字节
【解决方案2】:

清空列表后使用GC.Collect();

编辑:尝试FileProps=null; 代替清除。

【讨论】:

  • 同样的问题,GC.Collect 之后内存也没有释放。在任务管理器和 VS 诊断工具中观察应用程序消耗的内存大小
  • FileProps=null 后也出现同样的问题
猜你喜欢
  • 2013-08-27
  • 1970-01-01
  • 2018-03-16
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多