【问题标题】:Queue<T> memory usage and weird GC behaviorQueue<T> 内存使用和奇怪的 GC 行为
【发布时间】:2023-03-30 17:17:01
【问题描述】:

这是我正在玩的一个小型控制台程序,用于找出我的生产应用程序消耗过多内存的原因:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            Console.WriteLine("Press key - 1"); Console.ReadLine();

            var q = new Queue<string>();
            for (int i = 0; i < 1000000; i++)
                q.Enqueue("test string" + i);
            Console.WriteLine("Press key - 2"); Console.ReadLine();

            q = null;
            Console.WriteLine("Press key - 3"); Console.ReadLine();

            GC.Collect();
            Console.WriteLine("Press key - 4"); Console.ReadLine();

            GC.Collect(2);
            Console.WriteLine("Press key - 5"); Console.ReadLine();
}}}

我正在运行它并在按下键的同时监视 Windows 任务管理器。这是我在每个步骤的内存列中看到的内容:

  1. 4 700K
  2. 61 616K
  3. 61 596K
  4. 10 588K
  5. 8 588K

每次运行的结果略有不同(只有几 Ks),但您明白了。有人可以解释一下这里发生了什么吗?

我的环境:.NET4(客户端配置文件),Windows 7 x64。

【问题讨论】:

  • 没有投反对票,但是:这是垃圾收集,您正在向队列添加大量数据。仅仅因为您将其设置为 null 并不意味着它消耗的内存会立即被释放。通过强制 GC 运行,您可以将其删除(尽管这是一个坏主意)。 GC 将在需要时运行。
  • 谢谢!为什么在第 5 步我仍然消耗的内存是第 1 步的 2 倍?
  • 很难说,因为内存总量并没有告诉你任何关于消耗它的东西。可能是额外的程序集负载或被分页的框架的其他部分。您是在查看 VM 使用情况还是 RAM 使用情况?
  • 进程消耗的RAM使用量
  • 在探索内存“泄漏”和其他性能问题时,请尝试使用性能和内存分析器。见this question

标签: .net memory memory-leaks garbage-collection


【解决方案1】:

您发现了当您将局部变量设置为 null 时抖动不生成代码的原因。垃圾收集器已经知道你何时停止引用一个对象,它不需要这样的帮助。有很多关于 .NET 的书籍可以向您解释这一点,Richter 的“CLR via C#”广受好评。

【讨论】:

  • 为什么在第 3 步过程中仍然消耗 61Mb 的内存?
  • 因为垃圾收集器还没有运行。你为什么期望它运行?
  • 如果我增加样本中的字符串数量,所有内存都被消耗,机器开始交换,这不会触发 GC。为什么?
  • 你不能指望 GC 从队列中删除字符串,那将是灾难性的。它只能清理不使用的对象。
猜你喜欢
  • 1970-01-01
  • 2018-08-08
  • 2013-05-03
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
相关资源
最近更新 更多