Sunday, November 22, 2015

How to identify thread, which consumes most of process time in .NET application

Today we faced problem, that one of our services started consuming 50% of CPU after deployment. Luckily one of my colleagues already new how to investigate this issue.
So we will need two programs to process: WinDbg and ProcDump.
Let's assume we have following program which consumes 100% of processor time:

    class Program
    {
        static void Main(string[] args)
        {
            var rnd = new Random();
            while (true)
            {
                var number = rnd.NextDouble();
                Process(number);
            }
        }

        private static void Process(double input)
        {
            
        }
    }

Now, we need to create memory dump for process which causes problems. and that's why we need ProcDump. Execute following command:
procdump -ma PID
Flag -ma means, that we want full memory dump for our application.

Now start WinDbg(please not, that for 32bit application we will WinDbg(x86)) and open our dump: File->Open Crash Dump. To debug .NET applications, CLR support should be loaded, so execute following command:
.loadby sos clr
Now we need to execute runaway command, which shows us list running threads:
!runaway
For our program output of the command will be:
      User Mode Time
  Thread       Time
   0:3344      0 days 0:00:30.703
   7:1fc0      0 days 0:00:00.000
   6:1a64      0 days 0:00:00.000
   5:3a98      0 days 0:00:00.000
   
If we look at this output, we can see, that all process time was consumed by thread 0:3344. To switch to this thread we need to execute command:
~0s
where 0 is number before colon in thread ID. s means switch.
At this point we want to see call stack for this thread:
!clrstack
In my case I received following error: Symbols can not be loaded because symbol path is not initialized. To fix this I had to reload symbols with following commands:
.symfix
.reload
Execute !clrstack one more time and output at this time output will be:
OS Thread Id: 0x3344 (0)
Child SP       IP Call Site
00a9f114 715fa263 System.Random.InternalSample()
00a9f128 715fa20a System.Random.Sample()
00a9f130 7166c18d System.Random.NextDouble()
   
In case if we want to find memory leak, we can execute:
!dumpheap
And the output will be table with object name and number of objects of this type:
Statistics:
      MT    Count    TotalSize Class Name
71764cb0        3          468 System.Collections.Generic.Dictionary`2+Entry[[System.Type, mscorlib],[System.Security.Policy.EvidenceTypeDescriptor, mscorlib]][]
71764508        6          736 System.Int32[]
71763aac       52         1456 System.RuntimeType
717625fc       47         2586 System.String
717629f0        6        17528 System.Object[]
   

Tuesday, December 30, 2014

Windows+Docker+Redis

Today I've decided to investigate Docker, via doing simple task: installing Redis.

Let's assume that you already familiar with Chocolatey (package manager for Windows), and have installed.

Open powershell with administrative rights and intall Docker:

    choco install docker

After installation PC restart might be required(as in my case). Also, it will install Oracle VirtualBox, which has conflicts with Hyper-V, so probably you will have to uninstall last one.

Now we should start it:

     boot2docker up

Now let's connect to our machine:

    boot2docker ssh -L 6379:localhost:6379

You don't have to specify -L parameter, but we won't to access hour Redis instance from outside container, so we have to do port mapping. First port in paramenters is exposing port of our container(we will use it to connect to Redis). Second is inner host port. For more complex port mapping please check official documentation.

Next step is get Redis image from source:

    docker pull dockerfile/redis

At this point we are ready to start our instance:

    docker run -d --name redis -p 6379:6379 dockerfile/redis 

1st - outter container port (should match 2nd port from ssh command). 2nd - inner container port, this image uses redis default port 6379. More documents about starting redis here.

To stop and remove container execute next commands:

    docker stop redis
    docker rm redis

Thursday, December 25, 2014

Configuring Git client on Windows

Git is definitely must have tool for developer. In this article I will step by step show how to configure it on Windows. First start PowerShell with admin rights and change Execution Policy to something less restrictive:

    Set-ExecutionPolicy RemoteSigned

Next step to install Chocolatey, amazing package manager for Windows:

    iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 

Instead of installing raw Git client, we will use poshgit(Git for PowerShell), which provides nice to have futures:

    choco install poshgit 

To let git securely store credentials we will need one package:

    choco install git-credential-winstore

Right now, if you restart PowerShell most likely you will see warning "SSH Agent not found",in this case go to your PowerShell profile:  C:\Users\{UserName}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 and add at the beginning of file: $env:path += ";${env:ProgramFiles(x86)}\Git\bin"

Now you set.