人生是一场不能存盘的RPG,我只能尽量多搞几个Screenshot

May 26, 2006

Managed Heap Object pinned

Filed under: .NET

引自
OutOfMemoryException and Pinning
http://blogs.msdn.com/yunjin/archive/2004/01/27/63642.aspx

如果大量使用锁定的object,managed heap会被不可移动的内存块分割
成很多的小碎片,导致OutOfMemoryException.
比如Socket.BeginReceive的buffer参数就会被锁定, 以便unmanaged code 可以
访问这个buffer.

使用SOS可以发现
0:000>!dumpheap

     Address       MT     Size
     00a71000 0015cde8       12 Free
     00a7100c 0015cde8       12 Free
     00a71018 0015cde8       12 Free
     00a71024 5ba58328       68
     00a71068 5ba58380       68
     00a710ac 5ba58430       68
     00a710f0 5ba5dba4       68
     …
     00a91000 5ba88bd8     2064
     00a91810 0019fe48     2032 Free
     00a92000 5ba88bd8     4096
     00a93000 0019fe48     8192 Free
     00a95000 5ba88bd8     4096
     …
     total 1892 objects

     Statistics:
           MT    Count TotalSize Class Name
     5ba7607c        1        12 System.Security.Permissions.HostProtectionResource
     5ba75d54        1        12 System.Security.Permissions.SecurityPermissionFlag
     5ba61f18        1        12 System.Collections.CaseInsensitiveComparer
     …
     0015cde8        6     10260      Free
     5ba57bf8      318     18136 System.String
     …
    
以上数据表明在heap中有3个free slots
statistics一节显示heap中有10,260 bytes的Free objects和18,136 bytes 的字符串.
之所以可以看到这些free object,就说明这些free ojbect处在无法回收的live object之间.
如果heap中存在大量的Free objects,就表明heap中存在大量的内存碎片.

进一步可以使用
0:000>!dumpobj 00a92000    //00a92000 处的对象是一个byte array
   Name: System.Byte[]
   MethodTable 0x00992c3c
   EEClass 0x00992bc4
   Size 4096(0x1000) bytes
     Array: Rank 1, Type System.Byte
     Element Type: System.Byte
    
0:000>!gcroot 00a92000     //address 00a92000 it’s rooted by local variables in thread 1
   Scan Thread 0 (728)
     Scan Thread 1 (730)
     ESP:88cf548:Root:05066b48(System.IO.MemoryStream)->00a92000 (System.Byte[])
     ESP:88cf568:Root:05066b48(System.IO.MemoryStream)->00a92000 (System.Byte[])
     …
     Scan HandleTable 9b130
     Scan HandleTable 9ff18
     HANDLE(Pinned):d41250:Root: 00a92000 (System.Byte[])  //pinned handle.

0:000>!objsize   //显示所有pinned 对象的handle
    …
     HANDLE(Pinned):d41250: sizeof(00a92000) = 4096 ( 0x1000) bytes (System.Byte[])
     HANDLE(Pinned):d41254: sizeof(00a95000) = 4096 ( 0x1000) bytes (System.Byte[])
     HANDLE(Pinned):d41258: sizeof(00ac8b5b0) = 16 ( 0x10) bytes (System.Byte[])
     …

查看对象的详细信息,

可以采用以下措施来减小锁定 object的负面影响:
1.尽量使两个相邻的锁定 object挨得更紧.
2.尽量使锁定 object处在heap的底部,这是由于free的内存集中在heap的顶部.
3.缩短object被锁定的时间.
4.不要每次create一个对象,然后锁定它,而是重用被锁定的对象.

以下的代码演示如何使用一个1k的被锁定的buffer:

public class BufferPool
{
    private const int INITIAL_POOL_SIZE = 512; // initial size of the pool
    private const int BUFFER_SIZE = 1024; // size of the buffers

    // pool of buffers
    private Queue m_FreeBuffers;

    // singleton instance
    private static BufferPool m_Instance = new BufferPool();
    public static BufferPool Instance
    {
        get
        {
            return m_Instance;
        }
    }

    protected BufferPool()
    {
        m_FreeBuffers = new Queue(INITIAL_POOL_SIZE);
        for (int i = 0; i < INITIAL_POOL_SIZE; i++)
        {
            m_FreeBuffers.Enqueue(new byte[BUFFER_SIZE]);
        }
    }

    // check out a buffer
    public byte[] Checkout(uint size)
    {
        if (m_FreeBuffers.Count > 0)
        {
            lock (m_FreeBuffers)
            {
                if (m_FreeBuffers.Count > 0)
                    return (byte[])m_FreeBuffers.Dequeue();
            }
        }
      // instead of creating new buffer,
        // blocking waiting or refusing request may be better

        return new byte[BUFFER_SIZE];
    }

    // check in a buffer
    public void Checkin(byte[] buffer)
    {
        lock (m_FreeBuffers)
        {
            m_FreeBuffers.Enqueue(buffer);
        }
    }
}

 

Comments »

The URI to TrackBack this entry is: http://recordsome.blogsome.com/2006/05/26/managed-heap-object-pinned/trackback/

No comments yet.

RSS feed for comments on this post.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>



Anti-spam measure: please retype the above text into the box provided.






















Get free blog up and running in minutes with Blogsome
Theme designed by Hadley Wickham