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

May 26, 2006

Create Table

Filed under: SQL&DB Accessing

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N’[dbo].[_MyTable]’) AND type in (N’U'))

IF not exists (select * from dbo.sysobjects where id = OBJECT_ID(N’[dbo].[_MyTable]’) and OBJECTPROPERTY(id, N’IsUserTable’) = 1)
DROP TABLE [dbo].[_MyTable]
GO

CREATE TABLE [dbo].[_MyTable]
(
 [Test] [varchar](32)
)
GO

 

在Managed代码中慎用API

Filed under: .NET

引自
ExitThread() in managed program?
http://blogs.msdn.com/yunjin/archive/2004/01/30/65386.aspx

以下代码有问题吗?
[DllImport( "Kernel32.dll")]
public static extern void ExitThread(int exitCode);

public static void Run ()
{
    …
    // calling OS’s ExitThread to exit the current thread
    ExitThread (0);
}

public static void Main ()
{
    ThreadStart threadStart = new ThreadStart(Run);
    Thread thread = new Thread(threadStart);
    thread.Start();
    …
}

需要注意的是在CLR的控制下,某些系统调用在unmanaged和managed环境下的行为并不相同,
ExitThread就是其中一个,同时,managed threads 和unmanaged threads 也有所不同.
1.当一个managed thread退出时,比如线程处理函数返回或ThreadAbortException被抛出,
CLR会作一些清理的工作(比如stack unwinding),调用API ExitThread()或TerminateThread()
会绕过析构函数的调用,或finally 代码块.

2.在某些情况下,可能有好几个managed thread 被映射到一个OS thread,调用ExitThread 可能
会终止多个 managed thread.

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);
        }
    }
}

 

使用SOS

Filed under: WinDbg&SOS

//—-SOS.dll 的位置
%windir%\Microsoft.NET\Framework\<version>\

Documnet
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Tool Developers Guide\Samples\sos
.NET 2.0中这个目录不见了.

//—-让WinDbg加载SOS
当打开一个.net 可执行程序windbg6.5会自动加载SOS,如果需要手动加载,有如下方法

方法1:配置系统环境变量,让搜索路径指向系统.NET Framework的安装目录,既sos.dll所在目录
set PATH=%PATH%;C:\WINDOWS\Microsoft.NET\Framework\<Version>
然后使用.load SOS 加载

方法2. 加载某个特定的sos
.load <full path to sos.dll>

方法3.
.extpath command sets or displays the extension DLL search path.

方法4.
.loadby sos mscorwks
debugger 会加载模块mscorwks所在路径下的sos

方法5.
直接使用形如!DLLName.ExtensionCommand 的命令,如果扩展dll没有被加载,debugger会加载之.

在windbg6.5的安装目录下也有一个sos.dll
C:\Program Files\Debugging Tools for Windows\clr10
加载和使用方法如下:
.load clr10\sos
!clr10\sos.help

//—-相关命令

.load sos
加载SOS

.chain
list extensions dlls,以确认SOS是否正确加载

.setdll sos.dll 把SOS设置为default extension.

lm
查看有哪些模块被载入内存

//—–实验
用Windbg打开一个.net 可执行程序(ctrl+E), WinDbg会自动break到程序入口(如果attach到一个程序上,则
立即break),此时,mscorwks尚未被加载,如果在此时加载了SOS,SOS中的命令还无法使用.F5让程序继续运行,
这次WinDbg会自动break到,此时使用lm命令可以看到被加载的module,其中包含了mscorwks.dll,此时SOS中的命令
才可使用

参考
SOS: It’s Not Just an ABBA Song Anymore(John Robbins)
http://msdn.microsoft.com/msdnmag/issues/03/06/Bugslayer/

Mini Dump Snapshots and the New SOS(John Robbins)
http://msdn.microsoft.com/msdnmag/issues/05/03/Bugslayer/default.aspx

SOS Debugging of the CLR, Part 1
http://blogs.msdn.com/jasonz/archive/2003/10/21/53581.aspx

用WinDbg探索CLR世界
http://flier.cnblogs.com/archive/2004/07/08/22313.html

深入探索.NET框架内部了解CLR如何创建运行时对象
http://www.microsoft.com/china/MSDN/library/netFramework/netframework/JITCompiler.mspx?mfr=true

如何:使用 SOS
http://msdn2.microsoft.com/zh-cn/library/yy6d2sxs.aspx

SOS Debugging Extension (SOS.dll)
http://msdn2.microsoft.com/en-us/library/ms404370.aspx






















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