首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用什么C#语言机制将对象的实例传递给`GC.AddMemoryPressure`方法?

使用什么C#语言机制将对象的实例传递给`GC.AddMemoryPressure`方法?
EN

Stack Overflow用户
提问于 2020-02-26 19:52:05
回答 3查看 224关注 0票数 1

使用什么C#语言机制将对象的实例传递给GC.AddMemoryPressure方法?

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

代码语言:javascript
复制
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对remove an object while taking into an account the amp意味着什么?)

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-02-26 20:23:11

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

对象的实例通过调用AddMemoryPressure将它添加的压力与对自身的引用关联起来。对象本身已经有了标识!增加和消除压力的代码知道this是什么。

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

对,是这样。增加的压力与任何物体之间不一定有联系,无论是否存在,GC都不需要知道这些信息才能采取适当的行动。

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

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

而且,我没有看到调用GC.RemoveMemoryPressure(m_size)的任何理由

这样GC就知道附加的压力已经消失了。

我看不出放大器对GC有什么影响

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

我认为对这里发生的事情有一个根本的误解。

增加内存压力只是告诉GC,您知道有关内存分配的事实,而GC不知道,但与GC的操作相关。不要求添加的内存压力与任何对象的任何实例相关联,也不要求与任何对象的生存期相关联。

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

票数 7
EN

Stack Overflow用户

发布于 2020-02-26 20:03:40

这些方法的存在是为了让GC知道托管堆之外的内存使用情况。没有对象可以传递给这些方法,因为内存与任何特定的托管对象没有直接关联。代码的作者有责任正确地通知GC有关内存使用情况的变化。

GC.AddMemoryPressure(Int64)

…运行时只考虑托管内存,因此低估了调度垃圾收集的紧迫性。

极端的例子是您有32位的应用程序,GC认为它可以轻松地分配几乎2GB的托管(C#)对象。作为代码的一部分,您可以使用本机互操作来分配1GB。如果没有AddMemoryPressure调用,GC仍然认为等待分配/释放许多托管对象是免费的.但是,大约在分配1GB托管对象时,GC会遇到奇怪的状态--它应该有整个额外的GB来处理,但是没有什么剩下的了,所以它必须在这一点上加紧收集内存。如果AddMemoryPressure被正确使用,GC将有机会在更早的背景或允许更短/更小的影响的点上进行调整和更积极地收集。

票数 2
EN

Stack Overflow用户

发布于 2020-02-26 20:05:18

AddMemoryPressure用于声明(此处强调),您已经在某个地方分配了合理大小的非托管数据。此方法是运行时给予您的礼貌。

该方法的目的是在您自己的责任下声明您在某个地方拥有逻辑上绑定到某个托管对象实例的非托管数据。垃圾收集器有一个简单的计数器,并通过简单地将指定的数量添加到计数器来跟踪您的请求。

文档非常清楚:当非托管内存消失时,您必须告诉垃圾收集器它已经消失了。

您需要使用此方法通知垃圾收集器,非托管内存在那里,但如果释放关联对象,则可以释放。然后,垃圾收集器能够更好地安排其收集任务。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60421532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档