我有一个C#4.0应用程序(单个生产者/单个消费者),它以块的形式传输大量数据.虽然没有新的内存分配,但一段时间后内存不足.
我使用Redgate内存分析器分析了内存,那里有很多可用内存.它说由于碎片化而无法使用空闲内存.
我使用阻塞集合作为缓冲区和字节数组作为成员:
BlockingCollection<byte[]> segments = new BlockingCollection<byte[]>(8);
// producer:
segments.Add(buffer);
// consumer:
byte[] buffer = _segments.Take();
Run Code Online (Sandbox Code Playgroud)
如何避免托管内存碎片?
我问这个问题,以确定哪种内存分配算法可以为性能关键应用程序(如游戏引擎或嵌入式应用程序)提供更好的结果.结果实际上取决于内存碎片的百分比和内存请求的时间决定性.
教科书中有几种算法(例如Buddy内存分配),但也有其他像TLSF.因此,关于可用的内存分配算法,哪一个是最快的并且导致更少的碎片.顺便说一句,垃圾收集者不应包括在内.
还请注意,这个问题不是关于分析,它只是为了找出给定要求的最佳算法.
对于堆上和堆外分配.在堆上 - 在三个主要垃圾收集器的上下文中:CMS,Parallel Old和G1.
我所知道的(或者我认为我知道)到目前为止:
-XX:ObjectAlignmentInBytes.对于CMS,我发现的唯一相关信息是
自然旧的空间PLAB模仿索引自由列表空间的结构.每个线程预先分配一定数量的每个大小的块,低于257个堆字(从全局空间分配的大块).
来自http://blog.ragozin.info/2011/11/java-gc-hotspots-cms-promotion-buffers.html.据我所知,提到"全球空间"是主要的旧空间.
问题:
UPD.讨论主题:https://groups.google.com/forum/#!topic/mechanical-sympathy/ A- RImwuiFZE
java memory-management jvm-hotspot heap-fragmentation memory-fragmentation
在我的程序中,我看到一些居民规模增加.我想这是因为堆碎片.所以我打算用#pragma pack 1.它会减少堆碎片吗?
它会有其他一些开销吗?
我要不要去吧?
当我随机地使用malloc()s和free()s,嵌套并且具有不同的大小时,在某些时候内存将被分段,因为这些操作留下了大量的小内存区域,后面是非连续的,因此不能被分配为一个更大的块.
关于这个的一些问题:
如果经常这样做,以便内存被强制分段,然后所有这些内存区域都是free()d,我可以假设这些空闲区域连接回原来的连续大小吗?
当我总是执行a malloc()后跟free()相同的内存并且从不嵌套这些调用时,在分配/释放的大小总是不同的情况下,内存是否也在这种情况下碎片化?
我正在研究使用C++编写的大型服务器应用程序.此服务器可能需要运行数月而无需重新启动.由于我们的内存消耗随着时间的推移而增加,因此碎片已成为疑问.到目前为止,测量一直是将专用字节与虚拟字节进行比较,并分析这两个数字的差异.
我对碎片化的一般方法是将其留待分析.我有同样的方式来考虑其他事情,如一般性能和内存优化.您必须通过分析和证明来备份更改.
我在代码审查或讨论中注意到很多,内存碎片是最先出现的事情之一.这几乎就像现在对它的巨大恐惧一样,并且有一个很大的举措,就是提前"防止碎片化".请求代码更改似乎有利于减少或防止内存碎片问题.我倾向于不同意这些,因为它们似乎对我来说过早优化.我会牺牲代码的清洁度/可读性/可维护性等.为了满足这些变化.
例如,请使用以下代码:
std::stringstream s;
s << "This" << "Is" << "a" << "string";
Run Code Online (Sandbox Code Playgroud)
上面,字符串流在此处分配的数量是未定义的,它可以是4个分配,或者只是1个分配.因此我们不能仅基于此进行优化,但普遍的共识是使用固定缓冲区或以某种方式修改代码以潜在地使用较少的分配.我并没有真正看到stringstream在这里扩展自己是导致内存问题的一个巨大因素,但也许我错了.
以上代码的一般改进建议如下:
std::stringstream s;
s << "This is a string"; // Combine it all to 1 line, supposedly less allocations?
Run Code Online (Sandbox Code Playgroud)
尽可能在堆上使用堆栈也是一种巨大的推动力.
是否有可能以这种方式抢先处理内存碎片,或者这只是一种虚假的安全感?
有人可以告诉我为什么会发生以下事情:
我有2台电脑:
我维护C++程序(msvc 2005 c ++编译),它只在服务器上运行得太慢,但在我的comp上却没有.
我进行了测量(GetThreadTimes等)并且肯定可以说是狭窄的地方 - 它的内存分配(new/malloc).它只发生在服务器上!
我可以声称它是由于内存碎片而发生的,因为第一次服务器程序实例工作正常,只有在数据重新加载到内存(1-1.5百万分配/释放)后才开始在allocs上失去时间.
如果由于两台计算机(我的comp和服务器)上的内存碎片而看到相同的行为,我不会感到惊讶,但我看到的是:1).在我的comp分配上需要约5%的时间(不完全但有些像这样)2).在服务器上,这些分配需要大约75%的时间
怎么会发生这种情况?什么可能会减慢服务器计算机上的C++分配速度,同时它可以用于我的工作站.哪里可能有区别?它可能与OS级内存管理功能有关吗?因为C++级别管理器在两种情况下都是一样的.
以下是两种配置:
1).我的电脑(其中alloc占用约5%):
OS Name: Microsoft Windows 7 Enterprise
OS Version: 6.1.7600 N/A Build 7600
OS Manufacturer: Microsoft Corporation
OS Configuration: Member Workstation
OS Build Type: Multiprocessor Free
Registered Owner: Windows User
Original Install Date: 16/09/2011, 19:37:43
System Boot Time: 05/04/2013, 11:58:11
System Model: 7304A58
System Type: x64-based PC
Processor(s): 1 Processor(s) Installed.
[01]: Intel64 Family 6 Model 23 Stepping 10 GenuineIntel ~2642 Mhz
Windows Directory: C:\Windows …Run Code Online (Sandbox Code Playgroud) 在32位机器中,每个进程获得4GB虚拟空间.在这种情况下,人们可能会担心我们可能会因为碎片而面临麻烦.但是在64位机器的情况下,我们理论上有一个巨大的可寻址虚拟内存,那么为什么内存碎片仍然是一个问题(如果是)在64位机器上?
如果进程执行导致内存碎片,我们可以使用哪些机制来检测?
有没有相同的工具?对使用"C"代码并可在Windows,Linux和VxWorks上运行的工具的建议将会有所帮助.
我正在使用某些缓存算法,这在某种程度上具有挑战性.基本上,它需要分配许多小对象(双数组,1到256个元素),对象可通过映射值访问,map[key] = array.初始化数组的时间可能相当大,一般超过1万个cpu周期.
通过批量我的意思是总共约为千兆字节.可能需要根据需要弹出/推送对象,通常在随机位置,一次一个对象.对象的生命周期通常很长,几分钟或更长,但是,在程序持续期间,对象可能会被分配/释放多次.
什么是避免内存碎片的好策略,同时仍然保持合理的分配解除分配速度?
我正在使用C++,所以我可以使用new和malloc.谢谢.
我知道在网站上有类似的问题,有效地分配许多短命的小对象,有些不同,线程安全对我来说不是直接的问题.
我的开发平台是Intel Xeon,linux操作系统.理想情况下我也想在PPC linux上工作,但对我来说这不是最重要的.
c++ ×5
c ×4
memory ×2
allocation ×1
bytearray ×1
c# ×1
java ×1
jvm-hotspot ×1
malloc ×1
performance ×1