{"id":23175,"date":"2006-09-01T03:15:00","date_gmt":"2006-09-01T03:15:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/maoni\/2006\/09\/01\/understand-the-problem-before-you-try-to-find-a-solution\/"},"modified":"2021-10-04T16:34:30","modified_gmt":"2021-10-04T23:34:30","slug":"understand-the-problem-before-you-try-to-find-a-solution","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/understand-the-problem-before-you-try-to-find-a-solution\/","title":{"rendered":"Understand the problem before you try to find a solution"},"content":{"rendered":"<p><P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">So far I\u2019ve never written a blog entry that gives out philosophical advices on doing performance work. But lately I thought perhaps it\u2019s time to write such an entry because I\u2019ve seen enough people who looked really hard at some performance counters (often not correct ones) or some other data and asked tons of questions such as \u201cis this allocation rate too high? It looks too high to me.\u201d or \u201cmy gen1 size is too big, right? It seems big\u2026\u201d, <B>before<\/B> they have enough evidence to even justify such an investigation and questions.<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">Now, if you are just asking questions to satisfy your curious mind, that\u2019s great. I am happy to answer questions or point you at documents to read. But for people who are required to investigate performance related issues, especially when the deadline is close, my advice is \u201cunderstand the problem before you try to find a solution\u201d. Determine what to look at based on evidence, not based on your lack of knowledge in the area unless you already exhausted areas that you do know about. Before you ask questions related to GC, ask yourself if you think GC is actually the problem. If you can\u2019t answer that question it really is not a good use of your time to ask questions related to GC.<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">I\u2019ve seen many cases when something seems to go wrong in a managed application, people immediately suspect GC without any evidence to support that suspicion. Then they start to ask questions \u2013 often very random \u2013 hoping that they would somehow find the solution to fix their problem without understand what the problem is. That\u2019s not logical is it? So stop doing it!<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">So how do you know the right problems to solve, I would recommend the following:<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">1) Having knowledge about fundamentals really helps.<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">What are fundamentals? Performance in general comes down to 2 things \u2013 memory and CPU. Knowing basics of these 2 areas helps a lot in determining which area to look at. Obviously this involves a lot of reading and experimenting. I will list some memory fundamentals to get you started:<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">&nbsp;<\/FONT><\/P>\n<P class=\"MsoNormal\" align=\"center\"><B><SPAN><FONT size=\"2\"><FONT face=\"Verdana\">Some fundamentals of memory<\/FONT><\/FONT><\/SPAN><\/B><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\" size=\"2\">&nbsp;<\/FONT><\/SPAN><\/P>\n<P class=\"MsoListParagraph\"><SPAN><SPAN><FONT size=\"2\">\u00b7<\/FONT><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN><FONT size=\"2\"><FONT face=\"Verdana\">Each process has its own and separated virtual address space; all processes on the same machine share the physical memory (plus the page file if you have one). On 32-bit each process has a 2GB user mode virtual address space by default.<\/FONT><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\" size=\"2\">&nbsp;<\/FONT><\/SPAN><\/P>\n<P class=\"MsoListParagraph\"><SPAN><SPAN><FONT size=\"2\">\u00b7<\/FONT><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN><FONT size=\"2\"><FONT face=\"Verdana\">You, as an application author, work with virtual address space \u2013 you don\u2019t ever manipulate physical memory directly. If you are writing native code usually you use the virtual address space via some kind of win32 heap APIs (crt heap or the process heap or the heap you create) \u2013 these heap APIs will allocate and free virtual memory on your behalf; if you are writing managed code, GC is the one who allocates\/frees virtual memory on your behalf. <\/FONT><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\" size=\"2\">&nbsp;<\/FONT><\/SPAN><\/P>\n<P class=\"MsoListParagraphCxSpFirst\"><SPAN><SPAN><FONT size=\"2\">\u00b7<\/FONT><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN><FONT size=\"2\"><FONT face=\"Verdana\">Virtual address space can get fragmented \u2013 in other words, there can be \u201choles\u201d (free blocks) in the address space. When a VM allocation is requested, the VM manager needs to find one free block that\u2019s big enough to satisfy that allocation request \u2013 if you only got a few free blocks whose sum is big enough it won\u2019t work. This means even though you got 2GB, you don\u2019t necessarily see all 2GB used.<\/FONT><\/FONT><\/SPAN><\/P>\n<P class=\"MsoListParagraphCxSpMiddle\"><SPAN><FONT face=\"Verdana\" size=\"2\">&nbsp;<\/FONT><\/SPAN><\/P>\n<P class=\"MsoListParagraphCxSpLast\"><SPAN><SPAN><FONT size=\"2\">\u00b7<\/FONT><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN><FONT size=\"2\"><FONT face=\"Verdana\">VM can be in different states \u2013 free, reserved and committed. Free is easy. The difference between reserved and committed is what confused people sometimes. First of all, you need to recognized that they are different states. Reserved is saying \u201cI want to make this region of memory available for my own use\u201d. After you reserve a block of VM that block can not be used to satisfy other reserve requests. At this point you can not store any of your data in that block of memory yet \u2013 to be able to do that you have to commit it, which means you have to back it up with some physical storage so you can store stuff in it. When you are looking at the memory via perf counters and what not, make sure you are looking at the right things. You can get out of memory if you are running out space to reserve, or space to commit.<\/FONT><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\" size=\"2\">&nbsp;<\/FONT><\/SPAN><\/P>\n<P class=\"MsoListParagraph\"><SPAN><SPAN><FONT size=\"2\">\u00b7<\/FONT><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN><FONT size=\"2\"><FONT face=\"Verdana\">If you have a page file (by default you do) you can be using it even if your physical memory pressure is very low. What happens is the first time your physical memory pressure gets high and the OS needs to make room in the physical memory to store other data, it will back up some data that\u2019s currently in physical memory in the page file. And that data will not be paged in until it\u2019s needed so you can get into situations where the physical memory load is very low yet you are observing paging.<\/FONT><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\" size=\"2\"><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT size=\"2\"><FONT face=\"Verdana\"><\/FONT><\/FONT><\/SPAN>&nbsp;<\/P>\n<P class=\"MsoNormal\"><SPAN><FONT size=\"2\"><FONT face=\"Verdana\"><FONT color=\"#000000\">2) Knowing what your performance requirements are is a must.<\/FONT><\/FONT><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT face=\"Verdana\" color=\"#000000\" size=\"2\"><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><SPAN><FONT size=\"2\"><FONT face=\"Verdana\" color=\"#000000\"><\/FONT><\/FONT><\/SPAN>&nbsp;<\/P>\n<P class=\"MsoNormal\"><SPAN><FONT size=\"2\"><FONT face=\"Verdana\"><FONT color=\"#000000\">If you are writing a server application, it\u2019s very likely that you want to use all the memory and CPU that\u2019s available because people delicate the machine completely to run your app so why waste resources? If you are writing a client application, totally different story \u2013 you\u2019ll have to know how to cope with other applications running on the same machine. There\u2019re no rules such as \u201cyou have to make your app use as little memory as possible\u201d.<\/FONT><\/FONT><\/FONT><\/SPAN><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\"><\/FONT>&nbsp;<\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">When you\u2019ve decided that there is a problem, dig into it instead of guess what might be wrong. If your app is using too much memory, look at who is using the memory. If you\u2019ve decided that the managed heap is using too much memory, look at why. Managed heap using too much memory generally means you survive too much in your app. Look at what is holding on to those survivors.<\/FONT><\/P>\n<P class=\"MsoNormal\"><FONT face=\"Verdana\" size=\"2\">&nbsp;<\/FONT><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>So far I\u2019ve never written a blog entry that gives out philosophical advices on doing performance work. But lately I thought perhaps it\u2019s time to write such an entry because I\u2019ve seen enough people who looked really hard at some performance counters (often not correct ones) or some other data and asked tons of questions [&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":[3011,108],"class_list":["post-23175","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","tag-maoniposts","tag-performance"],"acf":[],"blog_post_summary":"<p>So far I\u2019ve never written a blog entry that gives out philosophical advices on doing performance work. But lately I thought perhaps it\u2019s time to write such an entry because I\u2019ve seen enough people who looked really hard at some performance counters (often not correct ones) or some other data and asked tons of questions [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23175","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=23175"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23175\/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=23175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=23175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=23175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}