Udostępnij za pośrednictwem


[Debugging Toolbox] Extracting Performance Monitor counters from .NET application

https://blogs.msdn.com/debuggingtoolbox/archive/2007/04/19/windbg-script-extracting-performance-monitor-counters-from-net-application.aspx

글 : Roberto Alexis Farah
번역 : 이태화

ASP.NET 에서 발생한 dump를 분석하면서 Performance Monitor log 를 얻는 것을 잊어버린던 경험이 있을 겁니다.

여러분이 이런 상황에 처해 있다면 제가 뉴스를 알려 드리겠습니다. 이 script 는ASP.NET Process 또는 Dump 에서 정보를 수집하여.NET Performance Monitor counter
들을 보여줍니다.

이 것은 제가 가지고 있는 좋은 script 중 하나 입니다.

PS : 전체 Module 에서 특정 값을 계산 한다던지 할때 유용한 방법일 것 같습니다.

screenshots:

설명:
lm1m - 모듈의 이름만을 얻을 수 있는 명령 .foreach 에서 사용됨
$sicmp - stricmp 와 같은 함수
${obj}!PerfCounters::m_pPrivatePerf - Module!Class::Member 를 접근하는 군요
as GCCounters .block - block 전체를 별명으로 설정해서 클릭으로 실행되게 하는군요

Source code for GET_PERFMON.TXT:

$$
$$ =============================================================================
$$ Get Performance Monitor counters from mscorsvr.dll or mscorwks.dll.
$$
$$ Compatibility: Win32.
$$
$$ Usage: $$>< to run the program.
$$
$$ Requirements: Public symbols.
$$
$$ If necessary change the filename below to include your path and filename.
$$ By default it uses the WinDbg path and the default file name is GET_PERFMON.TXT
$$
$$ Roberto Alexis Farah
$$ Blog: https://blogs.msdn.com/debuggingtoolbox/
$$
$$ All my scripts are provided "AS IS" with no warranties, and confer no rights.
$$ =============================================================================
$$
r @$t0 = 0;
r @$t1 = 0;
ad /q *
.block
{
    as ScriptName MYSCRIPTS\\GET_PERFMON.TXT
}
.foreach(obj { lm1m })
{
    .if((0 == $sicmp("${obj}", "mscorsvr")) | (0 == $sicmp("${obj}", "mscorwks")))
    {
        r @$t0 = ${obj}!PerfCounters::m_pPrivatePerf;
    }
}
.if(0 == @$t0)
{
    .printf /D " \nThis is not a .NET application!\n";
}
.else
{
    .block
    {
         .block
         {
             as GCCounters .block
                           {
                                    r @$t1 = poi(@$t0) + 0x4;
                                    .printf "\n.NET GC Counters\n\n";
                                    .printf "GenCollection 0           = 0n%d\n", poi(@$t1);
                                    .printf "GenCollection 1           = 0n%d\n", poi(@$t1+0x4);
                                    .printf "GenCollection 2           = 0n%d\n", poi(@$t1+0x8);
                                    .printf "PromotedMemory            = 0n%d\n", poi(@$t1+0xc);
                                    .printf "PromotedMemory 1          = 0n%d\n", poi(@$t1+0x10);
                                    .printf "PromotedFinalizationMem 0 = 0n%d\n", poi(@$t1+0x14);
                                    .printf "Process ID                = 0n%d\n", poi(@$t1+0x18);
                                    .printf "GenHeapSize 0             = 0n%d\n", poi(@$t1+0x1c);
                                    .printf "GenHeapSize 1             = 0n%d\n", poi(@$t1+0x20);
                                    .printf "GenHeapSize 2             = 0n%d\n", poi(@$t1+0x24);
                                    .printf "TotalCommittedBytes       = 0n%d\n", poi(@$t1+0x28);
                                    .printf "TotalReservedBytes        = 0n%d\n", poi(@$t1+0x2c);
                                    .printf "LargeObjectSize           = 0n%d\n", poi(@$t1+0x30);
                                    .printf "SurviveFinalize           = 0n%d\n", poi(@$t1+0x34);
                                    .printf "Handles                   = 0n%d\n", poi(@$t1+0x38);
                                    .printf "Alloc                     = 0x%x\n", poi(@$t1+0x3c);
                                    .printf "LargeAlloc                = 0x%x\n", poi(@$t1+0x40);
                                    .printf "InducedGCs                = 0n%d\n", poi(@$t1+0x44);
                                    .printf "TimeInGC                  = 0n%d\n", poi(@$t1+0x48);
                                    .printf "TimeInGCBase              = 0n%d\n", poi(@$t1+0x4c);
                                    .printf "PinnedObjects             = 0n%d\n", poi(@$t1+0x50);
                                    .printf "SinkBlocks                = 0n%d\n\n", poi(@$t1+0x54);
                          }
         }
         .block
         {
             as InteropCounters .block
                                {
                                          r @$t1 = poi(@$t0) + 0x74;
                                    .printf "\n.NET Interop Counters\n\n";
                                    .printf "CCW         = 0n%d\n", poi(@$t1);
                                    .printf "Stubs       = 0n%d\n", poi(@$t1+0x4);
                                    .printf "Marshalling = 0n%d\n", poi(@$t1+0x8);
                                    .printf "TLBImports  = 0n%d\n", poi(@$t1+0xc);
                                    .printf "TLBExports  = 0n%d\n\n", poi(@$t1+0x10);
                                }      
         }
         .block
         {
             as LoadingCounters .block
                                {
                                          r @$t1 = poi(@$t0) + 0x88;                                   
                                    .printf "\n.NET Loading Counters\n\n";
                                    .printf "Current ClassesLoaded = 0n%d\n", poi(@$t1);
                                    .printf "Total ClassesLoaded   = 0n%d\n", poi(@$t1+0x4);
                                    .printf "Current AppDomains    = 0n%d\n", poi(@$t1+0x8);
                                    .printf "Total AppDomains      = 0n%d\n", poi(@$t1+0xc);
                                    .printf "Current Assemblies    = 0n%d\n", poi(@$t1+0x10);
                                    .printf "Total Assemblies      = 0n%d\n", poi(@$t1+0x14);
                                    .printf "Time Loading          = 0n%d\n", poi(@$t1+0x18);
                                    .printf "AsmSearchLen          = 0n%d\n", poi(@$t1+0x20);
                                    .printf "Total LoadFailures    = 0n%d\n", poi(@$t1+0x24);
                                    .printf "LoaderHeapSize        = 0n%d\n", poi(@$t1+0x28);
                                    .printf "AppDomainsUnloaded    = 0n%d\n\n", poi(@$t1+0x2c);
                                }  
         }
         .block
         {
             as ExceptionCounters .block
                                  { 
                                          r @$t1 = poi(@$t0) + 0xb8;                                   
                                    .printf "\n.NET Exception Counters\n\n";
                                    .printf "Total Exceptions       = 0n%d\n", poi(@$t1);
                                    .printf "Filters Executed       = 0n%d\n", poi(@$t1+0x4);
                                    .printf "Finallys Executed      = 0n%d\n", poi(@$t1+0x8);
                                    .printf "ThrowToCatchStackDepth = 0n%d\n\n", poi(@$t1+0xc);
                                  }
         }
         .block
         {
             as LockAndThreadCounters .block
                                      {
                                                r @$t1 = poi(@$t0) + 0xc8;                                   
                                          .printf "\n.NET Locks and Threads Counters\n\n";
                                          .printf "Total Contention          = 0n%d\n", poi(@$t1);
                                          .printf "QueueLength Current       = 0n%d\n", poi(@$t1+0x4);
                                          .printf "QueueLength Total         = 0n%d\n", poi(@$t1+0x8);
                                          .printf "CurrentThreadsLogical     = 0n%d\n", poi(@$t1+0xc);
                                          .printf "CurrentThreadsPhysical    = 0n%d\n", poi(@$t1+0x10);
                                          .printf "RecognizedThreads Current = 0n%d\n", poi(@$t1+0x14);
                                          .printf "RecognizedThreads Total   = 0n%d\n\n", poi(@$t1+0x18);
                                      }
         }
         .block
         {
             as JITCounters .block
                            {
                                  r @$t1 = poi(@$t0) + 0xe4;                                   
                                .printf "\n.NET JIT Counters\n\n";
                                .printf "Methods Jitted    = 0n%d\n", poi(@$t1);
                                .printf "IL Jitted Current = 0n%d\n", poi(@$t1+0x4);
                                .printf "IL Jitted Total   = 0n%d\n", poi(@$t1+0x8);
                                .printf "JIT Failures      = 0n%d\n", poi(@$t1+0xc);
                                .printf "Time In JIT       = 0n%d\n", poi(@$t1+0x10);
                                .printf "Time In JIT Base  = 0n%d\n\n", poi(@$t1+0x14);
                            }
         }
         .block
         {
             as SecurityCounters .block
                                 {
                                      r @$t1 = poi(@$t0) + 0xfc;                                   
                                    .printf "\n.NET Security Counters\n\n";
                                    .printf "Total RunTime Checks     = 0n%d\n", poi(@$t1);
                                    .printf "Time Authorize           = 0n%d\n", poi(@$t1+0x4);
                                    .printf "Link Checks              = 0n%d\n", poi(@$t1+0xc);
                                    .printf "Time RunTime Checks      = 0n%d\n", poi(@$t1+0x10);
                                    .printf "Time RunTime Checks Base = 0n%d\n", poi(@$t1+0x14);
                                    .printf "Stack Walk Depth         = 0n%d\n\n", poi(@$t1+0x18);               
                                 }
         }
    } 
    .printf /D "<${ScriptName}\"> .NET GC Counters\n\n"
    .printf /D "<${ScriptName}\"> .NET Interop Counters\n\n"
    .printf /D "<${ScriptName}\"> .NET Loading Counters\n\n"
    .printf /D "<${ScriptName}\"> .NET Exception Counters\n\n"
    .printf /D "<${ScriptName}\"> .NET LocksAndThreads Counters\n\n"
    .printf /D "<${ScriptName}\"> .NET JIT Counters\n\n"
    .printf /D "<${ScriptName}\"> .NET Security Counters\n\n"
}