我有点困惑.在操作系统课程中,我们被告知所有操作系统都通过分页或分段来处理内存碎片,并且根本没有连续的物理内存分配.OS使用不同级别的寻址(逻辑/物理)来避免连续的内存分配.现在这里有很多关于它的讨论.我的问题是:在支持逻辑寻址的操作系统的c ++编程中,这个问题是否真实存在(任何进程是否因为内存碎片而崩溃)?如果是的话,为什么首先每个操作系统都试图避免连续寻址?
我有一个从大量MSMQ队列中读取的应用程序(目前约为10000).我使用queue.BeginPeekUInt32.MaxValue超时来从队列接收消息.当消息出现在队列中时,我处理它并queue.BeginPeek再次调用.所以我监听所有队列,但是消息处理是在线程池上完成的.
我注意到内存使用量缓慢增长(两周的工作量从200 MB增长到800 MB).在调查转储文件后,我看到了典型的堆碎片图片,其中包含许多自由对象(其中一些大小约为几兆字节).并且在孔之间存在固定物体.
在处理对非托管代码的调用时,这似乎是常见的情况,这些代码创建了固定对象.但我没有在互联网上找到任何解决方案.
那么.NET中的内存管理是如此纯粹,它甚至不允许完成这样简单的场景,或者我想念一些东西?
编辑:我在示例应用程序中进行了一些调查.在为新对象分配内存时,GC会重用固定对象之间的孔(可用内存区,即所谓的自由对象).但是在我的生产应用程序中,固定物体是长寿命的,它们最终出现在第二代,它们之间有孔(因为GC只是移动了分隔世代的边界).因为我的普通长寿对象很少,所以我在转储文件中看到了第二代的漏洞.
因此,我的应用程序的内存消耗可以增长到10000*(平均大小的孔).(10000是将来也可以增加的队列数).我现在不知道如何解决这个问题.唯一的方法是不时重新启动应用程序.
我再一次只能问,为什么.NET没有针对固定对象的单独堆?(也许这是新手问题).目前,我发现调用与非托管代码一起使用的异步操作可能会导致内存问题.
我正在尝试分配一些内存,但有时会出现"内存不足"的错误.cudaMemGetInfo说我需要更多的内存.所以,内存碎片问题.有可能解决这个问题吗?是不是可以将元素一个接一个地存放在存储器中,并且可以分解为我可以放在内存中的少量和平?
我一直在慢慢耗尽内存。我已经使用 WinDbg 来查看内存转储,这是它的样子:
000007f975ee0630 557377 41027736 System.Object[]
000007f975f004d0 18781 47746604 System.Byte[]
000007f975efc358 561433 54013658 System.String
000000000137b170 7616 1322123700 Free
Total 7627101 objects
Fragmented blocks larger than 0.5 MB:
Addr Size Followed by
000000004a9f62b0 18.2MB 000000004bc28050 System.Threading.OverlappedData
000000004dc2ce68 16.1MB 000000004ec522e8 System.Threading.OverlappedData
0000000050adaec0 10.3MB 0000000051525620 System.Threading.OverlappedData
000000005d47fd98 10.2MB 000000005deab618 System.Threading.OverlappedData
0000000071718ab8 23.0MB 0000000072e13a80 System.Threading.OverlappedData
0000000072e13e50 11.8MB 00000000739e4898 System.ServiceModel.Channels.SocketConnection
00000000801a7830 29.7MB 0000000081f5dd60 System.Threading.OverlappedData
000000008264ab58 14.0MB 000000008344bac0 System.Threading.OverlappedData
000000008344bb30 11.6MB 0000000083fecf80 System.Threading.OverlappedData
0000000083fecff0 13.6MB 0000000084d8dae8 System.Threading.OverlappedData
0000000084d8db58 148.3MB 000000008e1d65f8 System.Threading.OverlappedData
0000000093db04e0 19.4MB 00000000951158b8 System.Threading.OverlappedData …Run Code Online (Sandbox Code Playgroud) .net memory-leaks asynchronous memory-fragmentation .net-4.5
我正在使用ANTS内存分析器来诊断我在我的一个.NET 2.0应用程序中遇到的内存泄漏的增加.我在7.5小时的时间内拍摄了7个过程的快照,这里是获得的数据的表格表示 -

G1代表1代尺寸和G2代2尺寸.除非托管空间和专用字节外,所有其他值均以MB为单位.
我的问题是 -
为什么即使堆大小很低,也有如此高的未使用的.NET空间?
我的大对象堆最多大约2 MB,在最后3个快照中保持96 KB.那么为什么会出现如此高的大碎片,它们是否对未使用的空间负责?
不受管理的空间不断增加.这会导致私有字节数随时间增加吗?
我最终解决了这个问题,已经进行了多次分析,但无法找到适当的解决方案.我准备提供所需的任何其他数据.
我们在ASP.Net 4.0网站上遇到了每日OutOfMemoryExceptions.我们怀疑其中一个问题是LOH碎片,所以我们一直在寻找可以更有效地分配内存的代码更改.
例如,我们正在生成一个我们想要返回浏览器的大字符串(2mb).分页数据不是一种选择.
是否更有效:
Response.Write(bigString)or 进行一次调用Response.Write(smallString)如果我按照选项1然后我有一个大字符串占用LOH上的空格,然后被复制到Response对象的内部缓冲区.所以这似乎我现在至少暂时在LOH上有两个大块.
如果我按照选项2那么我正在处理大量的小字符串,这些字符串会被垃圾收集,并且只有LOH上的一个大块用于Response对象的缓冲区.
所以在我看来选项2更好.
我理解正确吗?
该服务器有4GB的Ram,并运行Windows 2003 32位.这是服务器上运行的唯一站点.因此每个进程都有一个4GB的地址空间,但只有2GB可用.当虚拟字节大约达到1.8Gb时,我们开始收到OOM错误,然后我们回收解决问题大约24小时的站点.专用字节在500-800mb之间变化.我认为问题不在于我们的物理内存不足.
背景短:
我正在开发一个应该运行数月并使用动态分配的系统.
问题:
我听说内存碎片减缓new和malloc运营商,因为他们需要在"洞"中的一个"发现"的地方,我留在了记忆,而不是在堆中简单的"前进".
我读过以下问题: 什么是内存碎片?
但是没有一个答案提到有关性能的任何内容,只有失败分配大内存块.
那么内存碎片会new花费更多时间来分配内存吗?如果是的话,多少钱?我如何知道是否new有"困难时间"在堆上查找内存?
我试图找到GCC用于在内存中找到"漏洞"以分配内部的数据结构/算法.但找不到任何血统的解释.
我正在运行一个服务HTTP请求的C#应用程序。我最近注意到,它占用的内存比我预期的要多。我抓起一些转储,将它们弹出到Windbg中,发现大部分内存都标记为“空闲”:
!dumpheap -stat
...
00007ffde4783630 681599 65433504 System.Threading.Tasks.TaskFactory+CompleteOnInvokePromise
00007ffde47cc988 167885 76872908 System.Byte[]
00007ffde47c6948 521353 80352802 System.String
0000007e3a16c2d0 1870425 1415374334 Free
Run Code Online (Sandbox Code Playgroud)
因此,转储约为3GB,因此其中约有一半是可用内存。看着堆,我看到了:
!heapstat
Heap Gen0 Gen1 Gen2 LOH
Heap0 82248472 7354560 987275056 178834656
Heap1 93146552 6382864 857470096 129435960
Total 175395024 13737424 1844745152 308270616
Free space: Percentage
Heap0 40969256 146456 640426720 54829792 SOH: 63% LOH: 30%
Heap1 75943736 94448 550812312 54825216 SOH: 65% LOH: 42%
Total 116912992 240904 1191239032 109655008
Run Code Online (Sandbox Code Playgroud)
因此,我的小对象堆非常分散,特别是Gen2。在服务器上,我可以看到gen2集合正在发生(使用性能计数器),但是即使它们是gen2堆,也似乎没有对其进行压缩。即使服务器上只有1-2%的RAM可用,gen2堆也不会被压缩。
在我看来,由于堆是零散的,所以我正遭受这种内存压力。但是我无法弄清楚为什么会发生碎片或为什么gen2无法压缩。一些可用空间的大小为6MB,所以我认为肯定可以将那些空间压缩掉。
谁能给我一些关于如何弄清楚我的堆为什么如此分散的想法?我什至在这里吠叫正确的树吗?
任何帮助将不胜感激,谢谢!
编辑1:
的细分!gchandles为:
Handles:
Strong Handles: 4507 …Run Code Online (Sandbox Code Playgroud) .net c# garbage-collection heap-fragmentation memory-fragmentation
我们在嵌入式系统环境中使用C++,基本上不需要任何类型的动态内存分配(例如,参见嵌入式应用程序中的内存管理资源,原因我们没有这样做).我们仍然不想没有一些很好的基于C++的功能,如STL容器和std :: string.对于第一个,我们在初始化时保留特定的大小,不会让容器超出其容量.对于后者(std :: string),我对如何"安全地"使用它们持怀疑态度,因为它们有时会在堆上分配内存.
但是,我发现使用std :: string(通常是堆分配对象的其他方式)似乎很好:我将对象本身分配到堆栈上(在{}我说话的某个范围内)来自C++)并允许它们分配堆,前提是它们在超出范围时实际释放所有保留的内存.
我知道这种方法并不能保证内存碎片的自由,但我觉得如果手头的范围是短暂的,这实际上会导致在范围结束后连续的空闲内存.
我还怀疑当多个任务共享相同的堆但仍然是空闲内存时最终可能存在问题,只要手头的范围都是短暂的(例如不阻塞).或者,我可以接受只允许一个任务在堆上分配内存,而其他任务实际上不重要.
我建议的堆分配对象的用法是否有效?有人有另一种策略(部分)启用动态内存分配而不会有内存碎片的风险吗?
我有一个基于 ARM 的无头 Linux (v3.10.53-1.1.1) 系统,没有启用交换空间,我偶尔会看到进程被 OOM 杀手杀死,即使有足够的 RAM 可用。
定期运行echo 1 > /proc/sys/vm/compact_memory似乎可以阻止 OOM 杀手,这让我认为内存碎片是罪魁祸首,但我不明白为什么用户进程无论如何都需要物理上连续的块;据我了解,即使在最坏的情况下(完全碎片,只有单独的 4K 块可用),内核也可以简单地分配必要数量的单独 4K 块,然后使用虚拟内存的魔力(tm)来制作它们看起来与用户进程连续。
有人可以解释为什么 OOM-killer 会被调用来响应内存碎片吗?这只是一个有缺陷的内核还是有真正的原因?(即使内核确实需要对内存进行碎片整理以满足请求,它难道不应该自动执行此操作而不是放弃并 OOM 吗?)
我在下面粘贴了一个 OOM-killer 调用示例,以防它对事情有任何启发。我可以随意重现故障;这个调用是在计算机仍然有大约 120MB 可用 RAM(根据free)时发生的,以响应我的测试程序分配内存,一次分配 10000 个 400 字节。
May 28 18:51:34 g2 user.warn kernel: [ 4228.307769] cored invoked oom-killer: gfp_mask=0x2084d0, order=0, oom_score_adj=0
May 28 18:51:35 g2 user.warn kernel: [ 4228.315295] CPU: 2 PID: 19687 Comm: cored Tainted: G O 3.10.53-1.1.1_ga+gf57416a #1
May 28 18:51:35 g2 user.warn kernel: [ 4228.323843] …Run Code Online (Sandbox Code Playgroud)