{"id":23171,"date":"2006-11-14T03:58:00","date_gmt":"2006-11-14T03:58:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/maoni\/2006\/11\/14\/my-application-seems-to-hang-what-do-i-do-part-2\/"},"modified":"2021-10-04T16:34:09","modified_gmt":"2021-10-04T23:34:09","slug":"my-application-seems-to-hang-what-do-i-do-part-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/my-application-seems-to-hang-what-do-i-do-part-2\/","title":{"rendered":"My application seems to hang. What do I do? \u2013 Part 2"},"content":{"rendered":"<p><P class=\"MsoNormal\"><A href=\"http:\/\/blogs.msdn.com\/maoni\/archive\/2006\/09\/28\/775111.aspx\"><FONT face=\"Verdana\" color=\"#800080\">Last time<\/FONT><\/A><FONT face=\"Verdana\"> I talked about the hang scenario where your process is taking 0 CPU and the CPU is taking by other process(es) on the same machine.<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">The next scenario is your process is taking 0 CPU and the CPU is barely used by other processes. <\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">As one of the readers correctly pointed out, this is very likely because you have a deadlock. Usually debugging deadlocks is relatively straightforward \u2013 you look at what the threads are waiting on and figure out which other threads are holding the lock(s). And there are plenty of online resources that talk about debugging deadlocks. If you use the <\/FONT><A href=\"http:\/\/www.microsoft.com\/whdc\/devtools\/debugging\/debugstart.mspx\"><FONT face=\"Verdana\">Windows Debugger package<\/FONT><\/A><FONT face=\"Verdana\"> there are built in debugger extension dlls that help you with this like !locks and etc. If you are debugging a managed app the <\/FONT><A href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms404370.aspx\"><FONT face=\"Verdana\" color=\"#800080\">SoS<\/FONT><\/A><FONT face=\"Verdana\"> debugger extension has commands that will aid you &#8211; !SyncBlk shows you managed locks (for CLR 2.0 there\u2019s also !Dumpheap \u2013thinlock for objects locked with ThinLocks instead of SyncBlk\u2019s).<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">Another possibility is your process is not doing any CPU related activities. A common activity is IO \u2013 for example if the process is heavily paging you will see almost 0 CPU usage but it appears hang because the memory it needs is getting loaded from the disk which is really slow. A very useful tool that shows you what processes are doing is <\/FONT><A href=\"http:\/\/www.microsoft.com\/technet\/sysinternals\/ProcessesAndThreads\/processmonitor.mspx\"><FONT face=\"Verdana\" color=\"#800080\">Process Monitor<\/FONT><\/A><FONT face=\"Verdana\">. Yesterday a program on my machine paused periodically \u2013 very annoying. So I used process monitor which showed me that this program periodically checks if I am logged onto my account in another program and since I am not, it would log me on, does a little bit stuff then log me off. And the hang was due to waiting on network IO. So to make it happy I logged myself on then the annoying periodic hang disappeared.<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">Now if your process is indeed taking CPU it can also appear to hang \u2013 as I mentioned last time this means different things for different people. If you have a UI app this can mean the UI is not getting drawn; if you have a server app this can mean your app is not processing requests. So you\u2019ll have to define what hang means to you. I will use server app not processing requests as an example. Usually server applications run on dedicated machines. So let\u2019s assume that\u2019s the case here \u2013 you run a server on a machine and the server could consist of multiple processes. You measure the server performance by throughput. One scenario is the CPU usage is high (perhaps even higher than usual) but the throughput is lower than usual.<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">The easiest case, as one of the readers pointed out, is an infinite loop \u2013 very easy to debug. You break into the debugger a few times and see a thread is taking all the CPU and that thread can not exit some function \u2013 so there goes your infinite loop. And if your process is pretty much the only process that uses CPU at the time this is super obvious. It gets a bit more complicated if you have multiple CPUs and other processes are also using CPUs. But still since it\u2019s an infinite loop the nice thing is it will always be executing if you don\u2019t interfere so it\u2019s always available to you to investigate as soon as it happens. <\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">It becomes hard if the hang only reproes sporadically and when it reproes it only lasts for a little while. Time to whip out a CPU profiler. As another reader pointed out, <\/FONT><A href=\"http:\/\/www.microsoft.com\/technet\/sysinternals\/utilities\/processexplorer.mspx\"><FONT face=\"Verdana\" color=\"#800080\">Process Explorer<\/FONT><\/A><FONT face=\"Verdana\"> is a useful tool to get you started. It shows you which processes are \u201cactive\u201d \u2013 meaning it\u2019s using CPUs. Personally I start with collecting appropriate performance counters, partially because pretty much all test teams in the product groups at Microsoft have some sort of automated testing procedure that collects perf counters so requesting them is easy. And because of the low overhead you can collect them for a long period of time so you have a histogram. <\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">These are the counters I usually request (comments in []\u2019s):<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><SPAN>Processor\\% Processor Time <\/SPAN><SPAN>for _Total and all processors<\/SPAN><SPAN><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\">[This is so I have an idea what kind of CPU usage I am looking at and if there are paticular processors that get used more than the rest]<\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><SPAN>Process\\% Processor Time <\/SPAN><SPAN>for all processes or less the ones that you already know can not be the problem<\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><\/SPAN>&nbsp;<\/P>\n<P class=\"MsoNormal\"><SPAN>Thread\\% Processor Time <\/SPAN><SPAN>for all processes or less the ones that you already know can not be the problem<\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\"><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\"><\/FONT><\/SPAN>&nbsp;<\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\">[The above counters will tell you which threads are using the CPU so you know which threads to look at]<\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\">&nbsp;<\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\">[Since I usually look at GC related issues I request all counters under .NET CLR Memory]<\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN>.NET CLR Memory counters <\/SPAN><SPAN>for all managed processes or less the ones that you already know can not be the problem<\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\">[If you are looking at other things you should add appropriate counters \u2013 for example, <SPAN>&nbsp;<\/SPAN>ASP.NET counters for apps that use ASP.NET]<\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\">&nbsp;<\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\">[If you know the kind of activities your processes do you can add appropriate counters for them. For me I often request memory related counters like:]<\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN>Memory\\% Committed Bytes In Use<\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN>Memory\\Available Bytes<\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN>Memory\\Pages\/sec<\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN>Process\\Private Bytes <\/SPAN><SPAN>for processes I am interested in<\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN>\u2026<\/SPAN><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">&nbsp;<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">At this point I can look at the results and concentrate on the interesting parts \u2013 for example when the CPU is usually high. I will have an idea which threads in what processes are consuming the CPU and the aspects of them that interest me (usually GC and other memory activities). Then I can request more detailed data on those processes\/threads. For example I can ask the person to use a sampling profiler so I can see what functions are executing in the part I am interested in (along with other info \u2013 this depends on what the profiler you are using is capable of). <\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\">Some people prefer to take memory dumps when the process hangs, sometimes this doesn\u2019t necessarily work (when it works it\u2019s great) because if the hang is related to timing\/how threads are scheduled the threads can easily behave differently when you interrupt it in order to take memory dumps so the hang may not repro anymore. If you do have consecutive dumps from one hang then you can use the !runaway command to see which threads have been consuming CPU. One dump is hardly useful for debugging hangs because it only gives you info at one point in time how the process behaves.<\/FONT><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time I talked about the hang scenario where your process is taking 0 CPU and the CPU is taking by other process(es) on the same machine. &nbsp; The next scenario is your process is taking 0 CPU and the CPU is barely used by other processes. &nbsp; As one of the readers correctly pointed [&hellip;]<\/p>\n","protected":false},"author":3542,"featured_media":58792,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[322,3011,108],"class_list":["post-23171","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","tag-debugging","tag-maoniposts","tag-performance"],"acf":[],"blog_post_summary":"<p>Last time I talked about the hang scenario where your process is taking 0 CPU and the CPU is taking by other process(es) on the same machine. &nbsp; The next scenario is your process is taking 0 CPU and the CPU is barely used by other processes. &nbsp; As one of the readers correctly pointed [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/3542"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=23171"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23171\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=23171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=23171"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=23171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}