草庐IT

c# - 当垃圾收集器在堆中移动数据时,引用是否会更新?

coder 2023-07-13 原文

我读到 GC(垃圾收集器)出于性能原因在堆中移动数据,我不太明白为什么,因为它是随机存取内存,可能是为了更好的顺序访问,但我想知道堆栈中的引用是否在这种情况下得到更新堆中发生移动。但也许偏移地址保持不变,但数据的其他部分被垃圾收集器移动,不过我不确定。

我认为这个问题与实现细节有关,因为并非所有垃圾收集器都可以执行此类优化,或者它们可以执行但不会更新引用(如果这是垃圾收集器实现中的常见做法)。但是我想得到一些特定于 CLR(公共(public)语言运行时)垃圾收集器的总体答案。

我还阅读了 Eric Lippert 的“引用不是地址”一文 here ,下面的段落让我有点困惑:

If you think of a reference is actually being an opaque GC handle then it becomes clear that to find the address associated with the handle you have to somehow "fix" the object. You have to tell the GC "until further notice, the object with this handle must not be moved in memory, because someone might have an interior pointer to it". (There are various ways to do that which are beyond the scope of this screed.)

对于引用类型,我们不想移动数据。那么我们在堆中还存储了什么,我们可以为了性能优化而四处移动?也许我们存储在那里的类型信息?顺便说一下,如果你想知道那篇文章是关于什么的,那么 Eric Lippert 将引用与指针进行了一点比较,并试图解释说引用只是地址可能是错误的,尽管 C# 是这样实现它的。

另外,如果我上面的任何假设是错误的,请纠正我。

最佳答案

是的,引用在垃圾回收期间得到更新。必然如此,当堆被压缩时对象被移动。压缩有两个主要目的:

  • 它通过更有效地使用处理器的数据缓存来提高程序的效率。这对现代处理器来说是一个非常非常大的问题,RAM 与执行引擎相比非常慢,胖了两个数量级。当处理器必须等待 RAM 提供变量值时,它可能会停止 数百 条指令。
  • 它解决了堆遭受的碎片问题。当释放一个被事件对象包围的小对象时,就会发生碎片。一个孔,只能用于大小相同或更小的物体。不利于内存使用效率处理器效率。请注意 LOH(.NET 中的大对象堆)如何不被压缩,因此会遇到这种碎片问题。 SO 对此有很多疑问。

不管 Eric 怎么说,对象引用实际上只是一个地址。指针,与您在 C 或 C++ 程序中使用的类型完全相同。非常有效,必然如此。移动对象后 GC 要做的就是更新存储在该指针中的地址到移动的对象。 CLR 还允许为对象分配句柄,额外 引用。在 .NET 中公开为 GCHandle 类型,但仅当 GC 需要帮助确定对象是否应保持事件状态或不应移动时才需要。仅当您与非托管代码互操作时才相关。

找到那个指针并不是那么简单。 CLR 投入了大量资金以确保能够可靠且高效地完成这项工作。这样的指针可以存储在许多不同的地方。更容易找回的是存储在对象字段、静态变量或 GCHandle 中的对象引用。硬的是存储在处理器堆栈或 CPU 寄存器中的指针。例如,发生在方法参数和局部变量上。

要实现这一点,CLR 需要提供的一个保证是 GC 始终可以可靠地遍历线程的堆栈。所以它可以找到存储在堆栈帧中的局部变量。然后它需要知道在哪里查看这样的堆栈帧,这是 JIT 编译器的工作。当它编译一个方法时,它不仅会为该方法生成机器代码,还会构建一个表来描述这些指针的存储位置。您将在 this post 中找到更多详细信息.

关于c# - 当垃圾收集器在堆中移动数据时,引用是否会更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27616910/

有关c# - 当垃圾收集器在堆中移动数据时,引用是否会更新?的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  3. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  6. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

  7. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  8. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  9. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  10. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

随机推荐