相关疑难解决方法(0)

大对象堆碎片

我正在研究的C#/ .NET应用程序正在遭受缓慢的内存泄漏.我已经使用CDB和SOS来尝试确定发生了什么,但数据似乎没有任何意义,所以我希望你们中的一个人之前可能已经经历过这种情况.

该应用程序在64位框架上运行.它不断地计算并将数据序列化到远程主机,并且正在大量地击中大对象堆(LOH).但是,我希望大多数LOH对象都是瞬态的:一旦计算完成并且已经发送到远程主机,就应该释放内存.然而,我所看到的是大量(实时)对象数组与空闲的内存块交织,例如,从LOH中获取一个随机段:

0:000> !DumpHeap 000000005b5b1000  000000006351da10
         Address               MT     Size
...
000000005d4f92e0 0000064280c7c970 16147872
000000005e45f880 00000000001661d0  1901752 Free
000000005e62fd38 00000642788d8ba8     1056       <--
000000005e630158 00000000001661d0  5988848 Free
000000005ebe6348 00000642788d8ba8     1056
000000005ebe6768 00000000001661d0  6481336 Free
000000005f214d20 00000642788d8ba8     1056
000000005f215140 00000000001661d0  7346016 Free
000000005f9168a0 00000642788d8ba8     1056
000000005f916cc0 00000000001661d0  7611648 Free
00000000600591c0 00000642788d8ba8     1056
00000000600595e0 00000000001661d0   264808 Free
...
Run Code Online (Sandbox Code Playgroud)

显然,如果我的应用程序在每次计算期间创建长寿命的大对象,我会期望这种情况.(它确实这样做,我接受会有一定程度的LOH碎片,但这不是问题.)问题是你可以在上面的转储中看到的非常小的(1056字节)对象数组,我在代码中看不到正在创建,并以某种方式保持根深蒂固.

另请注意,转储堆段时CDB不报告类型:我不确定这是否相关.如果我转储标记的(< - )对象,CDB/SOS报告正常:

0:015> !DumpObj 000000005e62fd38
Name: System.Object[]
MethodTable: 00000642788d8ba8
EEClass: 00000642789d7660
Size: 1056(0x420) bytes
Array: Rank 1, Number of elements 128, Type CLASS …
Run Code Online (Sandbox Code Playgroud)

.net c# memory-leaks memory-management windbg

96
推荐指数
2
解决办法
3万
查看次数

获取 LOH 中的对象实例列表

我在托管堆中存在数百个MyClass实例。其中一些位于大对象堆中。下面是各种堆结构的样子

0:000> !EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0000000002df9de8
generation 1 starts at 0x0000000002dc6710
generation 2 starts at 0x0000000002a01000
ephemeral segment allocation context: none
 segment     begin allocated  size
0000000002a00000  0000000002a01000  0000000002e3c2c0  0x43b2c0(4436672)
Large object heap starts at 0x0000000012a01000
 segment     begin allocated  size
0000000012a00000  0000000012a01000  000000001a5ed558  0x7bec558(129942872)
000000002a980000  000000002a981000  00000000328110b8  0x7e900b8(132710584)
0000000033e00000  0000000033e01000  000000003bd80d78  0x7f7fd78(133692792)
000000001daf0000  000000001daf1000  0000000025996188  0x7ea5188(132796808)
00000000542b0000  00000000542b1000  000000005a4bf100  0x620e100(102818048)
000000005c2b0000  000000005c2b1000  000000006344df88  0x719cf88(119132040)
000000007fff0000  000000007fff1000  00000000878bfbc0  0x78cebc0(126675904)
Total Size:              Size: …
Run Code Online (Sandbox Code Playgroud)

.net windbg sos large-object-heap sosex

5
推荐指数
1
解决办法
1425
查看次数

大对象堆碎片会导致 64 位进程中的 OutOfMemory 吗?

我正在准备向我的团队介绍 .net GC 和内存。不同的来源讨论了碎片对大对象堆的潜在影响。由于这将是一个有趣的现象,我试图在代码中展示它。

Thomas Weller 提供了这段代码,当尝试将更大的对象分配到 LOH 中的已释放间隙时,它看起来应该会导致 OOM,但由于某种原因它没有发生。LOH 是否在 .net 4.6 中自动压缩?LOH 碎片在 64 位中根本就不是问题吗?

来源:https : //stackoverflow.com/a/30361185/3374994

class Program
{
    static IList<byte[]> small = new List<byte[]>();
    static IList<byte[]> big = new List<byte[]>(); 

static void Main()
{
    int totalMB = 0;
    try
    {
        Console.WriteLine("Allocating memory...");
        while (true)
        {
            big.Add(new byte[10*1024*1024]);
            small.Add(new byte[85000-3*IntPtr.Size]);
            totalMB += 10;
            Console.WriteLine("{0} MB allocated", totalMB);
        }
    }
    catch (OutOfMemoryException)
    {
        Console.WriteLine("Memory is full now. Attach and debug if you like. Press Enter when …
Run Code Online (Sandbox Code Playgroud)

.net c# memory garbage-collection large-object-heap

5
推荐指数
1
解决办法
1247
查看次数

连接或添加字符串时的内存碎片,但不是string.Format?

所以大学的一位教授告诉我,在C#中使用串联连接(即当你使用加号运算符时)会产生内存碎片,而我应该使用它string.Format.

现在,我已经在堆栈溢出中搜索了很多,我发现了很多关于性能的线程,这些串联串起来.(其中一些包括这个,这个这个)

我找不到谈论内存碎片的人.我string.Format使用ILspy 打开了.NET ,显然它使用了与string.Concat方法相同的字符串构建器(如果我理解的是+符号被重载到的那个).实际上:它使用的代码string.Concat!

从2007年开始发现这篇文章,但我怀疑它今天(或永远!)是准确的.显然编译器足够聪明,可以避免今天,因为我似乎无法重现这个问题.使用string.format和plus符号添加字符串最终都会在内部使用相同的代码.如前所述,string.Format使用相同的代码字符串.Concat使用.

所以现在我开始怀疑他的主张.这是真的吗?

.net c# string string-concatenation memory-fragmentation

3
推荐指数
1
解决办法
889
查看次数

MemoryStream筋疲力尽

我正在将一些字节写入MemoryStream.我给它的大小为100 MB

  using (MemoryStream Stream = new MemoryStream())
        {             
                for ( loop 1400 time)
                {                        
                  func(i, OStream, Stream, );

                }

                lock (this)
                {                       
                 Stream.WriteTo(OStream);
                }
Run Code Online (Sandbox Code Playgroud)

}

func(i, OStream, Stream)
{
  loop 19 times
      get buffer;
   Stream.Write(buffer, 0, buffer.Length);
}
Run Code Online (Sandbox Code Playgroud)

缓冲区的byte[]大小从65536到116454不等.我循环1000次.我正在写for循环,但我得到OutOfMemoryException异常.

有没有办法扩展MemoryStream并避免异常?

c# memory-management

0
推荐指数
1
解决办法
252
查看次数