首页 > 解决方案 > 为了将对象的实例传递给“GC.AddMemoryPressure”方法,使用了哪些 C# 语言机制?

问题描述

为了将对象的实例传递给GC.AddMemoryPressure方法,使用了 C# 语言的哪些机制?

我通过 C# book在CLR中遇到了以下代码示例:

private sealed class BigNativeResource {
    private readonly Int32 m_size;
    public BigNativeResource(Int32 size) {
        m_size = size;
        // Make the GC think the object is physically bigger
        if (m_size > 0) GC.AddMemoryPressure(m_size);
        Console.WriteLine("BigNativeResource create.");
    }
    ~BigNativeResource() {
        // Make the GC think the object released more memory
        if (m_size > 0) GC.RemoveMemoryPressure(m_size);
        Console.WriteLine("BigNativeResource destroy.");
    }
 }

我不明白我们如何将一个对象的实例与它所增加的压力联系起来。我没有看到对象引用被传递给GC.AddMemoryPressure. 我们是否将增加的内存压力 (amp) 与对象相关联?

另外,我看不出有任何理由调用GC.RemoveMemoryPressure(m_size);. 从字面上看,它应该没有用。让我自己解释一下。有两种可能:对象实例之间存在关联,或者没有这种关联。

在前一种情况下,GC 现在应该m_size确定优先级并决定何时进行收集。因此,它绝对应该自行消除内存压力(否则 GC 对 GC 意味着什么remove an object while taking into an account the amp?)。

在后一种情况下,根本不清楚添加和移除放大器的用途。GC 只能使用定义为类实例的根。即GC只能收集对象。因此,如果对象和放大器之间没有关联,我看不出放大器如何影响 GC(所以我假设存在关联)。

标签: c#memory-managementgarbage-collectionmemory-pressure

解决方案


我不明白我们如何将一个对象的实例与它所增加的压力联系起来。

对象的实例通过调用将其添加的压力与对自身的引用相关联AddMemoryPressure。该对象已经与自己具有身份!添加和消除压力的代码知道是什么this

我没有看到对象引用被传递给 GC.AddMemoryPressure。

正确的。增加的压力与任何对象之间不一定存在关联,并且无论是否存在,GC 都不需要知道该信息以适当地采取行动。

我们是否将增加的内存压力 (amp) 与对象相关联?

GC 没有。如果您的代码这样做,那是您的代码的责任。

另外,我看不出有什么理由打电话给GC.RemoveMemoryPressure(m_size)

这样 GC 就知道额外的压力已经消失了。

我看不出放大器如何影响 GC

它会通过增加压力来影响 GC!


我认为对这里发生的事情存在根本性的误解。

增加内存压力只是告诉 GC 你知道一些关于内存分配的事实,而 GC 不知道,但与 GC 的动作有关。不要求增加的内存压力与任何对象的任何实例相关联或与任何对象的生命周期相关联

您发布的代码是一种常见模式:一个对象具有与每个实例相关联的额外内存,它会在分配额外内存时增加相应量的压力,并在释放额外内存时将其移除。但是不要求附加压力与一个或多个特定对象相关联。如果您在方法中添加了一堆非托管内存分配static void Main(),您可能会决定添加与其对应的内存压力,但没有与该额外压力相关联的对象。


推荐阅读