從頭開始使用WinDbg

從頭開始使用WinDbg 第一部分 web

基本配置: sql

1)  sos.dll 拷貝到WinDbg的安裝目錄,確保你拷貝的這個dll和你想要研究問題的程序的.net 版本一致。若是你同時在.net1.1  .net2.0下,你能夠把sos.dll 重命名爲 sos11.dll sos20.dll 或者把它們放在不一樣的目錄下面。 shell

2)  建立一個文件夾,用來放置你的符號文件,例如:「C:\symbols」 數組

3)  打開WinDbg,打開配置符號文件路徑的對話框 緩存

4)  輸入路徑,而且下載符號文件的路徑,當你的本地沒有符號文件的時候,它就須要去服務器上下載。結構以下: 服務器

srv*[cache path]*[symbols path] session

I'd recommend the following path: async

srv*c:\symbols\public*http://msdl.microsoft.com/download/symbols 工具

相信你已經設置好,下面開始了。 性能

 

頗有用的命令:

我會使用一個從IIS6上取來的dump文件來演示一些頗有用的命令。

第一件事要作的就是加載SOS,這個命令是 .load [extension filename] 這個結構很簡單。load 前面有一個  . 」。

.load sos

 

你如今已經有了一個很酷的帶有SOS擴展的命令提示工具。擴展命令都是以 !」前置的,所以若是你想運行一個幫助命令:

!help

若是你恰好有兩個擴展,並且分別有個命令,它們的名字是同樣的,你能夠這樣來分開它們:

![extension name].[command]

!sos.help

如今你知道了如何來運行命令,那麼運行help來看看,下面是給你的結果:

0:000> !help

-------------------------------------------------------------------------------

SOS is a debugger extension DLL designed to aid in the debugging of managed

programs. Functions are listed by category, then roughly in order of

importance. Shortcut names for popular functions are listed in parenthesis.

Type "!help " for detailed info on that function.

 

Object Inspection                  Examining code and stacks

-----------------------------      -----------------------------

DumpObj (do)                       Threads

DumpArray (da)                     CLRStack

DumpStackObjects (dso)             IP2MD

DumpHeap                           U

DumpVC                             DumpStack

GCRoot                             EEStack

ObjSize                            GCInfo

FinalizeQueue                      EHInfo

PrintException (pe)                COMState

TraverseHeap                       BPMD

 

Examining CLR data structures      Diagnostic Utilities

-----------------------------      -----------------------------

DumpDomain                         VerifyHeap

EEHeap                             DumpLog

Name2EE                            FindAppDomain

SyncBlk                            SaveModule

DumpMT                             GCHandles

DumpClass                          GCHandleLeaks

DumpMD                             VMMap

Token2EE                           VMStat

EEVersion                          ProcInfo

DumpModule                         StopOnException (soe)

ThreadPool                         MinidumpMode

DumpAssembly                      

DumpMethodSig                      Other

DumpRuntimeTypes                   -----------------------------

DumpSig                            FAQ

RCWCleanupList

DumpIL

更多的信息你能夠查看幫助,輸入 !help [name of command]

 

.time

這個不是SOS擴展命令,由於明顯它不是一個以「!」開頭的命令。Time 這個命令會顯示和時間有關係的信息。例如:系統啓動到如今的時間(uptime)、進程啓動到如今的時間,和在用戶和核心模式下的時間總和。

0:000> .time

Debug session time: Tue Oct 23 08:38:35.000 2007 (GMT+1)

System Uptime: 4 days 17:48:01.906

Process Uptime: 0 days 0:24:37.000

  Kernel time: 0 days 0:04:23.000

  User time: 0 days 0:03:28.000

你能夠看到系統已經啓動有4天多了,進程已經運行了24½ 分鐘。消耗的cpu時間總計是8分鐘。這樣咱們能夠獲得一個cpu使用率的大概是32.5%

 

!threadpool

咱們可使用這個命令完整的找出在dump文件在建立的時候得多少的cpu 使用率。並能獲得一些頗有用的信息,好比隊列中的工做請求數目,完整端口線程數目和計時器的數目。

0:000> !threadpool

CPU utilization 100%

Worker Thread: Total: 5 Running: 4 Idle: 1 MaxLimit: 200 MinLimit: 2

Work Request in Queue: 16

Unknown Function: 6a2d945d  Context: 023ede30

Unknown Function: 6a2d945d  Context: 023ee1e8

AsyncTimerCallbackCompletion TimerInfo@11b53760

Unknown Function: 6a2d945d  Context: 023ee3a8

Unknown Function: 6a2d945d  Context: 023e3040

Unknown Function: 6a2d945d  Context: 023ee178

Unknown Function: 6a2d945d  Context: 023edfb0

AsyncTimerCallbackCompletion TimerInfo@11b36428

AsyncTimerCallbackCompletion TimerInfo@11b53868

Unknown Function: 6a2d945d  Context: 023ee060

Unknown Function: 6a2d945d  Context: 023ee290

Unknown Function: 6a2d945d  Context: 023eded0

Unknown Function: 6a2d945d  Context: 023edd88

Unknown Function: 6a2d945d  Context: 023ede98

Unknown Function: 6a2d945d  Context: 023ee258

Unknown Function: 6a2d945d  Context: 023edfe8

--------------------------------------

Number of Timers: 9

--------------------------------------

Completion Port Thread:Total: 3 Free: 3 MaxFree: 4 CurrentLimit: 2 MaxLimit: 200 MinLimit: 2

因此咱們看見如今的cpu使用率是100%,而後咱們再看下一個命令。

 

!runaway

這是一個很好的命令,將會列出全部運行中的線程和cpu使用時間,這個是解決高cpu佔用率頗有用的一個命令。

0:000> !runaway

User Mode Time

  Thread       Time

  25:1a94      0 days 0:00:39.937

  16:1bc0      0 days 0:00:38.390

  50:1e8c      0 days 0:00:08.859

  52:1e40      0 days 0:00:08.687

  20:1c2c      0 days 0:00:08.234

  51:1340      0 days 0:00:08.171

  21:1bcc      0 days 0:00:06.953

  26:13ec      0 days 0:00:06.671

  44:131c      0 days 0:00:03.906

  22:d8c       0 days 0:00:03.375

  33:78c       0 days 0:00:02.656

你會看到這個總的時間和上面那個從.time命令中獲得的cpu 利用(cpu utilization)的時間不同,那是由於進程被重用了和回收了。這意味着總的cpu使用時間被若干個頁面請求線程分割了。

 

!threads

要獲得更多的運行線程信息,咱們能夠運行這個命令,這個會列出全部當前應用程序域下的託管線程。輸出相似以下:

0:000> !threads

ThreadCount: 48

UnstartedThread: 0

BackgroundThread: 29

PendingThread: 0

DeadThread: 19

Hosted Runtime: no

                                      PreEmptive   GC Alloc           Lock

       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception

  16    1 1bc0 001fccd0   1808220 Enabled  00000000:00000000 0019daf0     0 Ukn (Threadpool Worker)

  22    2  d8c 002016f0      b220 Enabled  00000000:00000000 0019daf0     0 MTA (Finalizer)

  14    4  4ac 00242e58   880a220 Enabled  00000000:00000000 0019daf0     0 MTA (Threadpool Completion Port)

  23    5 14a4 11b39f18    80a220 Enabled  00000000:00000000 0019daf0     0 MTA (Threadpool Completion Port)

  24    6 1d2c 11b41ad8      1220 Enabled  00000000:00000000 0019daf0     0 Ukn

  25    7 1a94 11b46c70   180b220 Enabled  27240c98:27241fd8 11b42540     1 MTA (Threadpool Worker)

  26    9 13ec 12ce2888   200b220 Enabled  2a9f1434:2a9f33c0 11b42540     0 MTA

  27    a 190c 12d85eb8   200b220 Enabled  00000000:00000000 11b42540     0 MTA

  29    b 1f5c 13df6a50   200b220 Enabled  2ab1da6c:2ab1f1c0 11b42540     0 MTA

那些ID XXXX 的線程是已經結束的,正在等待被回收。咱們能夠看見 一個 finalizer」的線程的ID號是22。所以當若是咱們運行 !runaway 命令看到一個不正常的活動的編號是22,那咱們如今知道是finalizer 的問題。

 

切換到某一個指定的進程

咱們使用 ~[number of thread]s ,因此若是要轉到50號進程,按下面的方法:

0:000> ~50s

若是咱們能切換到50號進程,那咱們有不少其餘有用的命令。

 

!clrstack

這個命令列出當前進程的調用堆棧。 -p」開關量能夠提供參數和局部變量的信息。

0:050> !clrstack

OS Thread Id: 0x1e8c (50)

ESP       EIP    

17a9e750 7d61c828

[NDirectMethodFrameSlim: 17a9e750]

 System.DirectoryServices.Protocols.Wldap32.ldap_bind_s(IntPtr, System.String,

System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX, System.DirectoryServices.Protocols.BindMethod)

17a9e768 14df70f9

System.DirectoryServices.Protocols.LdapConnection.BindHelper(System.Net.NetworkCredential, Boolean)

17a9e794 14df6de0 System.DirectoryServices.Protocols.LdapConnection.Bind()

17a9e79c 14df59e9

System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(System.DirectoryServices.Protocols.DirectoryRequest, Int32 ByRef)

17a9e8b8 14df56e8

System.DirectoryServices.Protocols.LdapConnection.SendRequest(System.DirectoryServices.Protocols.DirectoryRequest, System.TimeSpan)

17a9e8bc 14df5657 [InlinedCallFrame: 17a9e8bc]

從下讀到上,咱們能夠看到 調用了LdapConnectionSendRequest方法,該方法又調用了SendRequestHelper,這樣一層一層的。

0:050> !clrstack -p
OS Thread Id: 0x1e8c (50)
ESP       EIP     
17a9e750 7d61c828 [NDirectMethodFrameSlim: 17a9e750] System.DirectoryServices.Protocols.Wldap32.ldap_bind_s(IntPtr, System.String, System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX, System.DirectoryServices.Protocols.BindMethod)
17a9e768 14df70f9 System.DirectoryServices.Protocols.LdapConnection.BindHelper(System.Net.NetworkCredential, Boolean)
    PARAMETERS:
        this = 0x271fdfe0
        newCredential = 
        needSetCredential = 

17a9e794 14df6de0 System.DirectoryServices.Protocols.LdapConnection.Bind()
    PARAMETERS:
        this = 

17a9e79c 14df59e9 System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(System.DirectoryServices.Protocols.DirectoryRequest, Int32 ByRef)
    PARAMETERS:
        this = 0x271fdfe0
        request = 0x27246e38
        messageID = 0x17a9e8ec

17a9e8b8 14df56e8 System.DirectoryServices.Protocols.LdapConnection.SendRequest(System.DirectoryServices.Protocols.DirectoryRequest, System.TimeSpan)
    PARAMETERS:
        this = 0x271fdfe0
        request = 0x27246e38
        requestTimeout = 

17a9e8bc 14df5657 [InlinedCallFrame: 17a9e8bc]

 

咱們看看這些參數,好比傳遞到SendRequest  SendRequestHelper DirectoryRequest ,咱們要查看它的值,只要把地址記住,而後用下面的命令。

 

!dumpobject (!do)

這是另一個很是有用的命令,根據地址,能夠把一個對象dump出來,把requeset的地址傳過去,就能夠把這個對象dump出來

0:050> !do 0x27246e38
Name: System.DirectoryServices.Protocols.SearchRequest
MethodTable: 14b394c4
EEClass: 14d97ce0
Size: 52(0x34) bytes
GC Generation: 0
(C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices.Protocols\2.0.0.0__b03f5f7f11d50a3a\System.DirectoryServices.Protocols.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
02c39310  4000102        4        System.String  0 instance 00000000 directoryRequestID
14b398bc  4000103        8 ...ControlCollection  0 instance 27246e90 directoryControlCollection
02c39310  4000111        c        System.String  0 instance 27246d00 dn
12579f5c  4000112       10 ....StringCollection  0 instance 27246eb4 directoryAttributes
02c36ca0  4000113       14        System.Object  0 instance 27246ddc directoryFilter
14b39344  4000114       18         System.Int32  1 instance        1 directoryScope
14b393fc  4000115       1c         System.Int32  1 instance        0 directoryRefAlias
0fd3da00  4000116       20         System.Int32  1 instance        0 directorySizeLimit
1202af88  4000117       28      System.TimeSpan  1 instance 27246e60 directoryTimeLimit
120261c8  4000118       24       System.Boolean  1 instance        0 directoryTypesOnly

 

好的,那是什麼呢?它是System.DirectoryServices.Protocols.SearchRequest 對象,那就是說它有不少不一樣的由System.DirectoryServices.Protocols.SearchRequest類定義的屬性。能夠 查看msdn來知道更多的信息。它包含RequestId, Scope, DistinguishedName等字段。

讓咱們大膽的猜想 dn 這個東西里面是什麼東西。利用27246d00 這個地址,咱們來看看

0:050> !do 27246d00

Name: System.String

MethodTable: 02c39310

EEClass: 0fb610ac

Size: 112(0x70) bytes

GC Generation: 0

(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

String: CN=Dummy,CN=Accounts,CN=useradm,DC=dummy,DC=net

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

0fd3da00  4000096        4         System.Int32  1 instance       48 m_arrayLength

0fd3da00  4000097        8         System.Int32  1 instance       47 m_stringLength

0fb80010  4000098        c          System.Char  1 instance       43 m_firstChar

02c39310  4000099       10        System.String  0   shared   static Empty

    >> Domain:Value  0019daf0:03380310 11b42540:03380310 <<

0fb86d44  400009a       14        System.Char[]  0   shared   static WhitespaceChars

    >> Domain:Value  0019daf0:03380324 11b42540:033855bc <<

確切的說,裏面放的是"CN=Dummy,CN=Accounts,CN=useradm,DC=dummy,DC=net",若是你想找出更多的信息,能夠繼續用 !do 這個命令來檢查它們。

下一章,咱們繼續使用 !do 這些命令來分析dump文件,另外還會介紹更多的命令。

從頭開始使用WinDbg 第二部分

這是前面富有想像力的名字爲「從頭開始使用WinDbg 第一部分」的內容的繼續,我已經假設你已經讀過了它,所以,若是你尚未閱讀過,我強烈建議你先讀一下。咱們會繼續使用前面的dump例子,我很是樂意從上次咱們停下來的地方繼續前進。

 

更多有用的命令

上一次咱們使用了一些來自SOS擴展的很是好的命令來查看運行堆棧調用、請求、cpu中運行着的進程等等。咱們也向更深處挖掘了一些信息,咱們會繼續使用這些命令,還會有一些其餘命令。

 

!dumpstackobjects (!dso)

假設咱們正在查看一個特殊的進程,咱們想要知道被當前棧引用的全部託管對象。咱們有什麼方法能夠這麼作呢? 很是確定咱們有這樣一個命令:!dumpstackobjects 簡稱:dso

咱們運行這個命令,咱們就會看到當前進程的當前調用堆棧的全部對象的列表。輸出會像下面這樣:

由於篇幅關係僅列了一部份。

0:050> !dso

OS Thread Id: 0x1e8c (50)

ESP/REG  Object   Name

17a9e534 0741f860 System.RuntimeType

17a9e6b8 271fdfe0 System.DirectoryServices.Protocols.LdapConnection

17a9e6bc 27246f20

System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX

17a9e740 271fdfe0 System.DirectoryServices.Protocols.LdapConnection

17a9e744 27246f20

System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX

17a9e764 27246f20

System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX

17a9e768 271fdfe0 System.DirectoryServices.Protocols.LdapConnection

17a9e780 271fdfe0 System.DirectoryServices.Protocols.LdapConnection

當咱們想要看被當前進程單獨引用的全部對象的時候,這個命令很是的有用。若是你想要就某一個對象,你僅須要把地址拷貝下來,而後用 !dumpoubect 命令來查看。

0:050> !do 271fdfe0

Name: System.DirectoryServices.Protocols.LdapConnection

MethodTable: 14a2040c

EEClass: 149daf08

Size: 56(0x38) bytes

(C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices.Protocols\2.0.0.0__b03f5f7f11d50a3a\System.DirectoryServices.Protocols.dll)

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

14a2078c  40000c3        4 ...NetworkCredential  0 instance 00000000 directoryCredential

14a2144c  40000c4        8 ...ificateCollection  0 instance 271fe018 certificatesCollection

1202af88  40000c5       10      System.TimeSpan  1 instance 271fdff0 connectionTimeOut

1466fe50  40000c6        c ...rectoryIdentifier  0 instance 271fdf14 directoryIdentifier

14a2034c  4000236       24         System.Int32  0 instance        2 connectionAuthType

14a223a4  4000237       18 ...dapSessionOptions  0 instance 271fe2d8 options

0fb896d8  4000238       28        System.IntPtr  0 instance 564180944 ldapHandle

120261c8  4000239       2c       System.Boolean  0 instance        0 disposed

120261c8  400023a       2d       System.Boolean  0 instance        0 bounded

120261c8  400023b       2e       System.Boolean  0 instance        0 needRebind

14a22084  400023e       1c ...pResponseCallback  0 instance 271fe03c fd

120261c8  4000243       2f       System.Boolean  0 instance        0 setFQDNDone

120261c8  4000244       30       System.Boolean  0 instance        1 automaticBind

120261c8  4000245       31       System.Boolean  0 instance        1 needDispose

120261c8  4000246       32       System.Boolean  0 instance        1 connected

14a2267c  4000247       20 ...s.QUERYCLIENTCERT  0 instance 271fe394 clientCertificateRoutine

0fd314bc  400023c       20 ...ections.Hashtable  0   shared   static handleTable

    >> Domain:Value  0019daf0:NotInit  11b42540:073fe504 <<

02c36ca0  400023d       24        System.Object  0   shared   static objectLock

    >> Domain:Value  0019daf0:NotInit  11b42540:073fe53c <<

0fd314bc  400023f       28 ...ections.Hashtable  0   shared   static asyncResultTable

    >> Domain:Value  0019daf0:NotInit  11b42540:073fe610 <<

14a21864  4000240       2c ...lResultsProcessor  0   shared   static partialResultsProcessor

    >> Domain:Value  0019daf0:NotInit  11b42540:073fe678 <<

12305e94  4000241       30 ....ManualResetEvent  0   shared   static waitHandle

    >> Domain:Value  0019daf0:NotInit  11b42540:073fe64c <<

14a21954  4000242       34 ...lResultsRetriever  0   shared   static retriever

    >> Domain:Value  0019daf0:NotInit  11b42540:073fe6a8 <<

!dumparray (!da)

你可能已經注意到,咱們有再棧上一雙對象數組。查找 System.Object[] 類型,你會看到它們。 若是你對這個數組來執行 !dumpobject 命令,你只能看到數組自己的一些信息,而不是數組的內容。必須使用 !dumparray 簡稱 !da 命令來查看才能夠。

0:050> !do 27239b98

Name: System.Object[]

MethodTable: 02c3896c

EEClass: 02c388ec

Size: 24(0x18) bytes

Array: Rank 1, Number of elements 2, Type CLASS

Element Type: System.String

Fields:

None

 

0:050> !da 27239b98

Name: System.String[]

MethodTable: 02c3896c

EEClass: 02c388ec

Size: 24(0x18) bytes

Array: Rank 1, Number of elements 2, Type CLASS

Element Methodtable: 02c39310

[0] 272399a8

[1] 27239a44

你能夠看到 !dumparray 命令給了咱們多一點的信息。該數組包含了兩個System.String 的元素,而且有它們的地址。因此咱們可使用  !dumpobject 來查看這些String對象。

 

!objsize

你看上面列出的數組對象的大小是24B,這裏的大小僅僅是這個System.Object[] 這個對象本身的大小,僅表明這個結構的大小,並不包含它裏面的內容的大小。這個System.Object[]對象包含兩個String 對象,這些String 對象是獨立的對象,它們有32M的大小。因此24B並非這個數組的總大小,但它是正確的表示了System.Object[] 這個結構的大小隻有24B

要取得一個對象的大小咱們使用以下命令:

0:050> !objsize 27239b98

sizeof(27239b98) =          348 (       0x15c) bytes (System.Object[])

這個命令會遍歷這個對象所引用的的兒子對象和孫子對象等等。這個數組的精確的尺寸是包含了它子代的對象,大小是348B

若是裏面有不少的子代對象,使用 !objsize 這個命令來計算對象的大小是很慢的。你還有一點也是必須知道的,這個命令不是和你想象的這麼智能的。好比:你有一個自定義按鈕控件,它引用了父對象aspx 頁面對像,那麼你會獲得aspx 頁面的大小和它裏面子控件的大小。這樣是錯誤的,你獲得的 objsize會很是好笑得很大,你須要使用!dumpobject 來手動的確認一下引用的對象。

 

!dumpheap

這是另一個很是有用的命令。只用這個命令的時候你須要加一個參數,沒有參數的輸出會是整個堆上的全部對象。因此我通常都加上 –stat 這個參數。它本身內部會寫不少信息,但最後會有一個統計信息,下面是一段截取的輸出。

0:050> !dumpheap -stat

------------------------------

Heap 0

total 2754508 objects

------------------------------

Heap 1

total 2761329 objects

------------------------------

total 5515837 objects

Statistics:

      MT    Count    TotalSize Class Name

…….

14ef4718        1           12 System.Net.HttpRequestCreator

..

它是一個按照對象類型的大小來排列的,通常strings 都會排在最後面,由於它是用的最多的。另外比較有用的參數是 –type  –mt ,使用它們你能看到特別類型的對象。例如,你想看HttpRequestCreators這個對象,你可使用以下方式:

0:050> !dumpheap -mt 14ef4718       

------------------------------

Heap 0

Address       MT     Size

0342ccf8 14ef4718       12    

total 1 objects

------------------------------

Heap 1

Address       MT     Size

total 0 objects

------------------------------

total 1 objects

Statistics:

      MT    Count    TotalSize Class Name

14ef4718        1           12 System.Net.HttpRequestCreator

他會給咱們這個對象的地址,你想要更深刻的瞭解這個對象,就可使用 !dumpobject 這個命令。

!dumpheap –type 的工做也很是的類似,不一樣的是你此次是用類名,它會進行子字符串匹配,因此,若是你輸入:!dumpheap -type System.Web ,你就會獲得類名中包含「System.Web」的全部的類。

另外幾個比較有憂的參數是 –min  –max , 後面跟上一個表明對像大小的表明字節的數字。這個在你解決字符串問題時很是有用。另外,!dumpheap -stat -min 85000會列出全部的在LOH上的對象。-min 含義是除了  85000更小的。

 

把工具拿來使用

我會是用前面介紹的這些命令來進行一些實際的演示。這個dump文件是從前面一個case中獲得的。這個有問題的應用程序是運行在2個工做進程的web 園模式下。Session狀態是被放在sqlServer中的。客戶在測試性能的問題,對出現的問題的描述也是很模棱兩可的。我有好幾噸的dump要分析!所以,我大概的看看我能發現什麼。一件事,我在樂意很早就開始作的是查看cache。根據客戶所說,它們根本沒有使用cache。但我認爲一般最好再檢查一下。

爲了找出有多少數據被放在了cache中,我首先須要查找 System.Web.Caching.Cache 類。我運行 !dumpheap -stat -type System.Web.Caching.Cache ,注意我使用了 –stat 參數,不然我會獲得很長的信息,包括 Caching.CacheKeys  Caching.CacheEntrys等,下面是輸出。

0:050> !dumpheap -type System.Web.Caching.Cache -stat

------------------------------

Heap 0

total 665 objects

------------------------------

Heap 1

total 1084 objects

------------------------------

total 1749 objects

Statistics:

      MT    Count    TotalSize Class Name

123056f8        1           12 System.Web.Caching.CacheKeyComparer

1230494c        1           12 System.Web.Caching.Cache

……

……..

123063fc      832        16640 System.Web.Caching.CacheKey

12306820      732        52704 System.Web.Caching.CacheEntry

Total 1749 objects

我如今知道了 cache 對象,知道了Method Table ,我如今使用 !dumpobject 來列出這個對象

0:050> !dumpheap -mt 1230494c       

------------------------------

Heap 0

Address       MT     Size

03392d20 1230494c       12    

total 1 objects

------------------------------

Heap 1

Address       MT     Size

total 0 objects

------------------------------

total 1 objects

Statistics:

      MT    Count    TotalSize Class Name

1230494c        1           12 System.Web.Caching.Cache

Total 1 objects

如今知道了地址,那我就能夠運行 !objsize 來知道它到底有多少大,花費了一些時間,由於cache很複雜,並且還有不少子對象。結果出來了。

0:050> !objsize 03392d20

sizeof(03392d20) =    266640828 (   0xfe49dbc) bytes (System.Web.Caching.Cache)

cache  266MB ,這是很是多的,但事實中,客戶說它們並無使用cache

那什麼被緩存了呢?

爲了抽取一些樣本看看什麼被緩存了,我看了看 CacheEntrys。我已經有了MethodTable,剛纔在執行 !dumpheap -type System.Web.Caching.Cache –stat(前面)的時候已經有了這個MT,因此有下面的輸出:

0:050> !dumpheap -mt 12306820     

------------------------------

Heap 0

Address       MT     Size

033950bc 12306820       72    

033a20d8 12306820       72    

033ac79c 12306820       72    

033da21c 12306820       72    

....etc...

03e160f8 12306820       72   

total 382 objects

------------------------------

total 732 objects

另一個可使用的命令,有相同的輸出的,我已經給出的,固然是:

!dumpheap -type System.Web.Caching.CacheEntry

OK,讓咱們看看這個CacheEntrys,抽取一些樣本,我執行了:

0:050> !do 03b2c674

Name: System.Web.Caching.CacheEntry

MethodTable: 12306820

EEClass: 122f6470

Size: 72(0x48) bytes

(C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

02c39310  4001327        4        System.String  0 instance 03b2c600 _key

0fb8f1f8  4001328        c          System.Byte  0 instance        2 _bits

0fd3da00  4001329        8         System.Int32  0 instance -1314181915 _hashCode

02c36ca0  4001330       10        System.Object  0 instance 03b2c644 _value

120219d0  4001331       1c      System.DateTime  1 instance 03b2c690 _utcCreated

120219d0  4001332       24      System.DateTime  1 instance 03b2c698 _utcExpires

根據已經dump出來的結果,我最感興趣的是 _value,所以我把地址拷貝下來,而後運行:

0:000> !do 03e160c8

Name: System.Web.SessionState.InProcSessionState

MethodTable: 14dbad5c

EEClass: 14e43af8

Size: 48(0x30) bytes

(C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

1466c9d8  4001d89        4 ...ateItemCollection  0 instance 1a7f5438 _sessionItems

1292672c  4001d8a        8 ...ObjectsCollection  0 instance 00000000 _staticObjects

0fd3da00  4001d8b        c         System.Int32  0 instance       20 _timeout

120261c8  4001d8c       18       System.Boolean  0 instance        0 _locked

120219d0  4001d8d       1c      System.DateTime  1 instance 03e160e4 _utcLockDate

0fd3da00  4001d8e       10         System.Int32  0 instance        1 _lockCookie

1202bf60  4001d8f       24 ...ReadWriteSpinLock  1 instance 03e160ec _spinLock

0fd3da00  4001d90       14         System.Int32  0 instance        0 _flags

這裏我發現了頗有趣的一個東西,被緩存的東西是一個InProcSessionState對象,這個東西之前可能不知道是放在緩存裏的吧。有了這個對象,那麼客戶說的它們使用sqlServer來保存Session是不正確的。

結果是這樣的:客戶臨時爲了概要性地檢測把它改爲了In-process 模式,可是忘記把它改爲SqlServer模式了。

從頭開始使用WinDbg 第三部分(高級命令)

你知道麼,你可使用一些 for eache if 等來構建你的高級命令。下面列出了控制關鍵詞:

.if

.else

.elseif

.foreach

.for

.while

.do

.break

.continue

.catch

.leave

.printf

.block

 

使用這些關鍵詞,你能夠給調試器發送不少高級指令,那會讓你的工做更加的簡單。極大的提高你的工做成果。

..foreach

讓咱們從一個簡單的例子開始,假如你想研究堆上全部大於65000字節或更大的字符串。 要列出它們你只要輸入:!dumpheap -type System.String -min 6500

0:000> !dumpheap -type System.String -min 6500

------------------------------

Heap 0

Address       MT     Size

790da154 790f9244     9280    

0264c4d0 790f9244    32788    

total 2 objects

------------------------------

Heap 1

Address       MT     Size

total 0 objects

------------------------------

Heap 2

Address       MT     Size

0b62e790 790f9244    11284    

total 1 objects

------------------------------

Heap 3

Address       MT     Size

0e6839d0 790f9244    32788    

0e717904 790f9244    32788    

0fb2a320 790f9244     6828    

total 3 objects

------------------------------

total 6 objects

Statistics:

      MT    Count    TotalSize Class Name

790f9244        6       125756 System.String

Total 6 objects

如今的問題是這樣的,爲了研究每個字符串,你須要對每個地址運行 !dumpobject 這個命令,在這裏也許是能夠接受的,但若是有25 100個怎麼辦呢? 不知道你是否注意到了這一點。若是你 經過 –short 這個參數,那!dumpheap 會給你最少的信息,僅僅是每一個對象的地址

0:000> !dumpheap -type System.String -min 6500 -short

790da154

0264c4d0

0b62e790

0e6839d0

0e717904

0fb2a320

------------------------------

如今讓咱們來用 .foreache 子句吧。

0:000> .foreach(myVariable {!dumpheap -type System.String -min 6500 -short}){!do myVariable;.echo *************}

Name: System.String

MethodTable: 790f9244

EEClass: 790f91a4

Size: 9280(0x2440) bytes

(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

String:

WFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWGRkAiEPDxYCHwEFZFhYWFhYWFhYWFhYWFhYWFhYWFhYWF

hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhY

WFhYWFhYWFhYWFhkZAInDw8WCh8CBQFFHwMFCjIyLzExLzIwMDcfBAUBVh8FBQFFHwYFASpkZAIpD2QWBGYPZBYEAg

ETC...

 

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

790fdb60  4000096        4         System.Int32  1 instance     4632 m_arrayLength

790fdb60  4000097        8         System.Int32  1 instance     4631 m_stringLength

790fad38  4000098        c          System.Char  1 instance       3c m_firstChar

790f9244  4000099       10        System.String  0   shared   static Empty

    >> Domain:Value  000d5eb8:790d57b4 000fb4c0:790d57b4 000ca848:790d57b4 1d8334d8:790d57b4 <<

79122994  400009a       14        System.Char[]  0   shared   static WhitespaceChars

    >> Domain:Value  000d5eb8:026203f0 000fb4c0:02624504 000ca848:026745f0 1d8334d8:026dcef4 <<

*************

Name: System.String

MethodTable: 790f9244

EEClass: 790f91a4

。。。。。。。

因爲篇幅的關係,這裏僅列出一部分。讓咱們來分析一下

.foreach    (myVariable

{!dumpheap -type System.String -min 6500 -short}

)

{!do myVariable;.echo *************}

 

myVariable 和它的字面意思同樣,是變量名,我但願用它來存放由第一個命令子集的輸出數據。第二個命令子集是來執行循環的,首先運行!do,而後我使用 .echo 命令來輸出一個分割符,這樣便於閱讀。

還有更多的參數你可使用。能夠查看幫助來獲得更多的信息。

 

.shell

我第一次看見個人一個同事使用過這個命令,他是一個調試方面的專家。

0:000> .shell -i - -ci "!iisinfo.clientconns" FIND /c "Request active"

40

.shell: Process exited

它首先運行 !iisinfo.clientonns」,而後用MS Dos  FING 命令來計算字符串「Request active」出現的次數。固然你能夠再任何輸出中來搜索特定的字符串。例如「」shell -i - -ci "!do 0b62e790" FIND /c /i "<table" 」,或其餘你須要的東西。

讓咱們很快的看一下這個結構: -i」是可選的,用來指定輸入,這裏咱們不使用文件,因此咱們使用一個連字符(hyphen)。「.shell  –i  – 」,使用 「-ci」的意思是把緊跟的命令看成輸入。最後咱們指定 用怎麼樣的shell 命令來處理輸入:「 FIND /c "Request active"  。事實上,你可使用任意複雜的命令來代替「!iisinfo.clientconns」,好比說一個 foreach 循環。

相關文章
相關標籤/搜索