我们都知道,.net的GC是不会压缩大对象堆的,因为其时间开销不可接受,但这是以大对象堆产生大块碎片为代价的,如果以后要分配的大对象比最大的碎片还大,那么即使它比所有碎片的总大小要小,也是无法在不扩展大对象堆的前提下分配成功的,此时有可能引发内存不足的异常。

我想到一个方案,可以让大对象堆也能压缩,而且时间开销在可接受的范围内,原理是利用页表。我们知道,程序能看到的内存地址都是虚拟地址,是通过页表映射到物理地址的,连续的虚拟地址对应的物理地址未必连续,反之亦然。在内存中移动大量数据,开销很大,因为数据真的要在物理内存上复制,但如果我们不动物理内存上的数据,只修改页表及其缓存TLB,即修改了物理地址与虚拟地址的映射关系,开销就会小得多,而且对于应用程序来说,同样达到了内存移动的效果。(物理内存上没有数据移动,但对象的虚拟地址却变了,对应用程序来说,这就是数据移动了!)

当然,如果要用这种方法实现压缩大对象堆,也会有一些局限性:比如每个大对象必须占据整数页的空间,且大对象的起始地址必须是某页的起始地址,这样大对象之间会出现一些小碎片(不会超过一页的大小,即不超过4K,与85K以上的大对象本身相比,还是很小的),但小碎片总比大碎片好呀,就看怎么权衡了,而且这些小碎片也是可以被利用的,比如可以把一些大小合适的2代小对象存储到这些小碎片中,以节约小对象堆的空间。

PS: 现在的一些虚拟机软件的实现似乎就使用了类似的方法,以达到提高效率的目的。

该问题的英文讨论贴:https://github.com/dotnet/coreclr/issues/555

C# 内存管理优化畅想(一)---- 大对象堆(LOH)的压缩的更多相关文章

  1. C# 内存管理优化畅想----前言

    C#语法简洁.优雅,类库丰富,是我最喜爱的计算机语言,没有“之一”.但是,经过深入学习后发现,C#的内存管理,也就是通常所说的垃圾回收(GC)机制,虽然跟其他支持GC的语言相比,已经很优秀了,但与手动 ...

  2. C# 内存管理优化畅想(二)---- 巧用堆栈

    这个优化方法比较易懂,就是对于仅在方法内部用到的对象,不再分配在堆上,而是直接在栈上分配,方法结束后立即回收,这将大大减轻GC的压力. 其实,这个优化方法就是java里的逃逸分析,不知为何.net里没 ...

  3. C# 内存管理优化畅想(三)---- 其他方法&结语

    前两篇文章提出的优化方法,都是不需要修改源代码的,而是在CLR或JIT层面进行自动优化的.但本文中提出的优化方法则需要引入新的语法,开发者只有在源代码中使用了这些新语法,才会获得优化. 1. 允许对象 ...

  4. [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少大对象堆的碎片,在某些情况下强制执行完整GC,按需压缩大对象堆,在GC前收到消息通知,使用弱引用缓存对象

    减少大对象堆的碎片 如果不能完全避免大对象堆的分配,则要尽量避免碎片化. 对于LOH不小心就会有无限增长,但LOH使用的空闲列表机制可以减轻增长的影响.利用这个空闲列表,我们可以在两块分配区域中间找到 ...

  5. oc45--多对象内存管理 优化

    // // main.m // Set方法的内存管理 #import <Foundation/Foundation.h> #import "Person.h" #imp ...

  6. C# 内存管理优化实践

    内存优化畅想系列文章已经结束了,很多读者读完之后可能觉得“然并卵”,毕竟都是给微软提的建议而已,现在都没有实现.那么为了优化内存,有没有什么我们现在就能用的技巧呢?我的答案是:有.网上关于.net内存 ...

  7. EasyDarwin开源流媒体服务器内存管理优化

    -本文由EasyDarwin开源团队成员Fantasy贡献 前言 最近在linux上跑EasyDarwin发现一个很奇怪的问题,当有RTSPSession连接上来的时候,发现进程的虚拟内存映射一下就多 ...

  8. 一文了解.Net的CLR、GC内存管理

    一文了解.Net的CLR.GC内存管理 微软官方文档对内存管理和CLR的概述 什么是托管代码? 托管代码就是执行过程交由运行时管理的代码. 在这种情况下,相关的运行时称为公共语言运行时 (CLR),不 ...

  9. .Net 垃圾回收和大对象处理

    CLR垃圾回收器根据所占空间大小划分对象.大对象和小对象的处理方式有很大区别.比如内存碎片整理 —— 在内存中移动大对象的成本是昂贵的,让我们研究一下垃圾回收器是如何处理大对象的,大对象对程序性能有哪 ...

随机推荐

  1. JS模块加载器加载原理是怎么样的?

    路人一: 原理一:id即路径 原则.通常我们的入口是这样的: require( [ 'a', 'b' ], callback ) .这里的 'a'.'b' 都是 ModuleId.通过 id 和路径的 ...

  2. 推荐用于格式化以及高亮显示SQL文的PHP类-SqlFormatter

    有时候做开发用到SQL文的时候,由于sql文太长,很难真正看清楚这个sql文的结构. 所以需要一个工具能够自动对SQL文进行排版,在网上有幸找到这个用php写的类能处理这个任务. 原文地址是http: ...

  3. bzoj 1067: [SCOI2007]降雨量 模擬

    1067: [SCOI2007]降雨量 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2010  Solved: 503[Submit][Status] ...

  4. h.264宏块与子宏块类型

    宏块类型mb_type 宏块类型表示的是宏块不同的分割和编码方式,在h.264的语法结构中,宏块类型在宏块层(macroblock_layer)中用mb_type表示(请参考h.264语法结构分析中的 ...

  5. 在keil中使用Astyle格式化你的代码的方法

    一个好的程序,不仅要有好的算法,同时也需要有良好的书写风格.写出好的算法不容易,但是好的代码风格却并不困难.提到格式化代码,Astyle是一个不能错过的工具,它可以方便的将程序代码格式化成自己想要的样 ...

  6. Guava的一些总结

    guava是java API蛋糕上的冰激凌(精华). 源码包的简单说明:  com.google.common.annotations:普通注解类型.  com.google.common.base: ...

  7. android 判断程序是首次(第一次)进入

    很多时候,我们需要判断用户是不是第一次进入程序,以决定是不是给用户一些操作提示. 这种功能的实现,说到底还是将数据(一个标志位)存储起来,下次进入程序的时候读取数据进行判断. 我这里只给出一种较简单的 ...

  8. UVA 586 Instant Complexity

    给出一段程序,求运行时间. 现在只考虑一层LOOP,不妨用数组a[i]来表示n的i次方的系数.如果输入OP m,那么就在a[0]上加m,遇到END,就说明循环结束了,需要在系数上乘以循环次数.如果次数 ...

  9. C++ 1

    1 new 建立一个堆对象 new 类名(初值列表) 返回一个指针 int * p=new int(3)动态分配 2 delete  释放指针 delete p; delete [] p ;释放动态申 ...

  10. 【HDOJ】1394 Minimum Inversion Number

    逆序数的性质.1. 暴力解 #include <stdio.h> #define MAXNUM 5005 int a[MAXNUM]; int main() { int n; int i, ...