代码之家  ›  专栏  ›  技术社区  ›  J D

你能重新编译这个64位.NET 4 GC错误吗?

  •  16
  • J D  · 技术社区  · 14 年前

    update: Microsoft现在已经复制了错误并正在进行修复。

    在评估.NET平台用于低延迟软件开发的可行性时,我们在.NET 4并发工作站垃圾收集器中发现了一个严重的错误,该错误会导致应用程序一次挂起多达几分钟。

    在我们的三台机器上,以下简单的C程序会导致GC泄漏内存,直到没有剩余内存,然后启动一个巨大的GC循环,使程序暂停几分钟。当11GB的堆被回收时:

    static void main(string[]args)
    {
    var q=new system.collections.generic.queue<system.object>();
    虽然(真)
    {
    Q.EngRead(0);
    如果(Q.Count>1000000)
    q.DEQueReo();
    }
    }
    < /代码> 
    
    

    您需要使用.NET 4在64位Windows操作系统上编译x64,并使用默认(并发工作站)GC运行,使用默认(交互式)延迟设置。

    以下是任务管理器在此计算机上运行此程序时的外观:

    请注意,当此程序不需要超过100MB的内存时,此处泄漏了11GB的堆。

    我们现在已经积累了大约12个用F和C编写的bug的repros,当大多数gen0生存时,它似乎与gc写入屏障中的bug有关。然而,微软还没有能够复制它。你能?如果是这样,您能尽可能准确地描述您的设置吗?这样我们就可以尝试缩小此错误显示所需的具体条件。

    在评估.NET平台用于低延迟软件开发的可行性时,我们发现.NET 4并发工作站垃圾收集器中存在严重的错误,这可能导致应用程序一次挂起长达几分钟。

    在我们的三台机器上,以下简单的C程序会导致GC泄漏内存,直到没有剩余内存,然后启动一个庞大的GC循环,使程序暂停几分钟(!)当11GB的堆被回收时:

        static void Main(string[] args)
        {
            var q = new System.Collections.Generic.Queue<System.Object>();
            while (true)
            {
                q.Enqueue(0);
                if (q.Count > 1000000)
                    q.Dequeue();
            }
        }
    

    您需要在64位Windows操作系统上使用.NET 4编译x64,并使用默认(交互)延迟设置使用默认(并发工作站)GC运行。

    以下是任务管理器在此计算机上运行此程序时的外观:

    alt text

    注意,当这个程序不需要超过100MB的内存时,这里泄漏了11GB的堆。

    我们现在已经积累了大约12个用F和C编写的bug的repros,当大多数gen0生存时,它似乎与gc写入屏障中的bug有关。然而,微软还没有能够复制它。你能?如果是这样,您能尽可能准确地描述您的设置吗?这样我们就可以设法缩小这个bug显示所需的具体条件。

    3 回复  |  直到 9 年前
        1
  •  2
  •   Eamon Nerbonne    14 年前

    如果以64位运行,在linqpad中运行代码确实会导致巨大的内存消耗;以32位运行可以很好地工作。

    我有一个Windows7x64UltimateInstall(像往常一样修补),主内存为8GB;安装了vs.net和其他dev工具,因此可能有一些奇怪的调试器挂钩,而这些挂钩在其他空白计算机上不存在。

    奇怪的是他们没有责备。你确定那里没有通讯故障吗?

    哦,使用“new object()”而不是装箱的值类型会导致相同的问题(毫不奇怪),因此您可能希望从repro案例中删除装箱的混淆因素。

        2
  •  3
  •   Naveen    9 年前

    我不能复制它。我在X64上尝试了它,它有4个Gigs RAM,编译为任何一个。最大内存使用率约为2.5 gigs。最大GC暂停时间约为1084 ms。

    这是我的gc etw统计数据的输出。

    您还可以按时间获取GC事件

    可能运行中类似的跟踪输出有助于理解在封面下发生了什么。

    在.NET 4.0中,有提供框架跟踪信息的Windows事件跟踪(ETW)。以下是特定于 gc的文件。

    为了获得这些信息,有一个工具叫做perfview,它被称为 perfview

    以下是使用该工具获取GC信息的步骤

    1. 以管理员身份启动一个cmd.exe,这是收集ETW跟踪所必需的
    2. 启动要跟踪的应用程序
    3. 发出命令perfmonitor.exe/process:4180 start,其中4180是进程ID
    4. 让应用程序运行一段时间
    5. 然后发出perfmonitor.exe stop
    6. 获取报告perfmonitor.exe gctime的命令。这将生成一个报告,并用gc状态在浏览器中打开它。
    RAM编译为任意。最大内存使用率约为2.5 gigs。最大GC暂停时间约为1084 ms。

    这是我的gc etw统计数据的输出。 alt text

    您还可以按时间获取GC事件 alt text

    可能运行中类似的跟踪输出有助于理解在封面下发生了什么。

    在.NET 4.0中,有提供框架跟踪信息的Windows事件跟踪(ETW)。这是特定于 GC .

    为了得到这些信息,有一个工具叫做 PerfView

    以下是使用该工具获取GC信息的步骤

    1. 以管理员身份启动一个cmd.exe,这是收集ETW跟踪所必需的
    2. 启动要跟踪的应用程序
    3. 发出命令perfmonitor.exe/process:4180 start,其中4180是进程ID
    4. 让应用程序运行一段时间
    5. 然后发出perfmonitor.exe stop
    6. 获取报告perfmonitor.exe gctime的命令。这将生成一个报告,并用gc状态在浏览器中打开它。
        3
  •  2
  •   J D    14 年前

    我在博客上写过这个 here 到目前为止,除了我和eamon之外,还有六个人已经证实他们也可以复制这个bug。

    此外,卡斯滕和迈克尔·罗宾独立地重复了我的怀疑,即这种病毒并非在每次运行中都会立即出现,而是随机出现,有时会在正常运行几十分钟后出现。换句话说,默认的.NET垃圾收集器是概率的,可能会导致停机,并随机持续几分钟。