How do .NET profilers work? - c#

I am thinking about adding a diagnostics mode build into an app I am writing to count method usage and execution time, similar to what many code profilers like dotTrace do.
I'm having some trouble finding resources through google on how to accomplish this though; obviously it is possible, but can anyone point me to some resources on how I can implement something like method call counts in .NET?

The Code Project article Creating a Custom .NET Profiler describes the process of creating a profiler using the CLR profiler hooks.
This involves creating a COM object that implements the ICorProfilerCallback2 interface and then using environment variables to indicate to the CLR that we wish to profile by using this class:
When the CLR begins a process, it looks for two environment variables:
COR_ENABLE_PROFILING: This environment variable is set to either 1 or 0. 1 indicates that the CLR should use a profiler. 0 (or the non-existence of this environment variable) indicates that it should not use a profiler.
COR_PROFILER: Now that we've told the CLR that we want to profile, we have to tell it which profiler to use. Because profilers are implemented as COM objects, this environment variable will be set to the GUID of the coclass that implements the ICorProfilerCallback2 interface.

Perhaps I am being too simple here, but my solution to this would be logging. Using entlib or log4net and log debug level messages. Then you can just write a little script/program to analyse the log file and give you the method count. There might even be other log diagnostic tools.
Unless you need rich visualization or real time complex relationship mapping etc. Would you need a profiler? For method count and execution time, wouldn't a log file suffice? Once you are in production or don't care about instrumentation you turn your logging level up and forget about those debug messages.

Related

Limiting the allowed RAM for a service, possible using MaxWorkingSet

I have a service that runs on a domain controller that is randomly accessed by other computers on the network. I can't shutdown the service and run it only when needed (this would defeat the purpose of running it as a service anyway).
The problem is that the memory used by the service doesn't seem to ever get cleared, and increases every time the service is queried by a remote computer.
Is there a way to set a limit on the RAM used by the application?
I've found a few references to using MaxWorkingSet, but none of the references actually tell me how to use it. Can I use MaxWorkingSet to limit the RAM used to, for example, 35MB? and if so, how? (what is the syntax etc?)
Otherwise, is there a function like "clearall()" that I could use to reset the variables and memory at the end of each run through? I've tried using GC.Collect(), but it didn't work.
Literally, MaxWorkingSet only affect Working set, which is the amount of physical memory. To restrict of an overall memory usage, you need Job Object API. But it is danger if your program really need such memory (many codes don't consider an OutOfMemoryException and sometimes .NET runtime has strange behaviors when memory is not enough)
You need to:
Create a Win32 Job object
Set the maximum memory to the job
Assign your process to the job
Here is a wrapper for .NET. ^reference
Besides, you could try this method of GC: (for .NET 4.6 or newer)
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect(2, GCCollectionMode.Forced, true, true);
(for older but sometimes doesn't work)
GC.Collect(2, GCCollectionMode.Forced);
The third param in 4.6 version of GC.Collect() is to tell runtime whether to do garbage collecting immediately. In older versions, GC.Collect() only notifies and leaves the decision to runtime.
As for some programming advice, I suggest you could wrap a class for one query. The class could be explicitly disposed after a query is done. It may help make GC smarter.
Finally, indeed there are something in .NET framework which you need to manage yourself. Like Bitmap.GetHBitmap, they need to be disposed manually.

I've found a bug in the JIT/CLR - now how do I debug or reproduce it?

I have a computationally-expensive multi-threaded C# app that seems to crash consistently after 30-90 minutes of running. The error it gives is
The runtime has encountered a fatal error. The address of the error was at 0xec37ebae, on thread 0xbcc. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
(0xc0000005 is the error-code for Access Violation)
My app does not invoke any native code, or use any unsafe blocks, or even any non-CLS compliant types like uint. In fact, the line of code that the debugger says caused the crash is
overallLength += distanceTravelled;
Where both values are of type double
Given all this, I believe the crash must be due to a bug in the compiler or CLR or JIT. I'd like to figure out what causes it, or at the very least write a smaller reproduction to send into Microsoft, but I have no idea where to even begin. I've never had to view the CIL-binary, or the compiled JIT output, or the native stacktrace (there is no managed stacktrace at the time of the crash), so I'm not sure how. I can't even figure out how to view the state of all the variables at the time of the crash (VS unfortunately won't tell me like it does after managed-exceptions, and outputting them to console/a file would slow down the app 1000-fold, which is obviously not an option).
So, how do I go about debugging this?
[Edit] Compiled under VS 2010 SP1, running latest version of .Net 4.0 Client Profile. Apparently it's ".Net 4.0C/.Net 4.0E, .Net CLR 1.1.4322"
I'd like to figure out what causes it, or at the very least write a smaller reproduction to send into Microsoft, but I have no idea where to even begin.
"Smaller reproduction" definitely sounds like a great idea here... even if "smaller" won't mean "quicker to reproduce".
Before you even start, try to reproduce the error on another machine. If you can't reproduce it on another machine, that suggests a whole different set of tests to do - hardware, installation etc.
Also, check you're on the latest version of everything. It would be annoying to spend days debugging this (which is likely, I'm afraid) and then end up with a response of "Yes, we know about this - it was a bug in .NET 4 which was fixed in .NET 4.5" for example. If you can reproduce it on a variety of framework versions, that would be even better :)
Next, cut out everything you can in the program:
Does it have a user interface at all? If possible, remove that.
Does it use a database? See if you can remove all database access: definitely any output which isn't used later, and ideally input too. If you can hard code the input within the app, that would be ideal - but if not, files are simpler for reproductions than database access.
Is it data-sensitive? Again, without knowing much about the app it's hard to know whether this is useful, but assuming it's processing a lot of data, can you use a binary search to find a relatively small amount of data which causes the problem?
Does it have to be multi-threaded? If you can remove all the threading, obviously that may well then take much longer to reproduce the problem - but does it still happen at all?
Try removing bits of business logic: if your app is componentized appropriately, you can probably fake out whole significant components by first creating a stub implementation, and then simply removing the calls.
All of this will gradually reduce the size of the app until it's more manageable. At each step, you'll need to run the app again until it either crashes or you're convinced it won't crash. If you have a lot of machines available to you, that should help...
tl;dr Make sure you're compiling to .Net 4.5
This sounds suspiciously like the same error found here. From the MSDN page:
This bug can be encountered when the Garbage Collector is freeing and compacting memory. The error can happen when the Concurrent Garbage Collection is enabled and a certain combination of foreground Garbage Collection and background Garbage Collection occurs. When this situation happens you will see the same call stack over and over. On the heap you will see one free object and before it ends you will see another free object corrupting the heap.
The fix is to compile to .Net 4.5. If for some reason you can't do this, you can also disable concurrent garbage collection by disabling gcConcurrent in the app.config file:
<configuration>
<runtime>
<gcConcurrent enabled="false"/>
</runtime>
</configuration>
Or just compile to x86.
WinDbg is your friend:
http://blogs.msdn.com/b/tess/archive/2006/02/09/net-crash-managed-heap-corruption-calling-unmanaged-code.aspx
http://www.codeproject.com/Articles/23589/Get-Started-Debugging-Memory-Related-Issues-in-Net
http://www.codeproject.com/Articles/22245/Quick-start-to-using-WinDbg
Download Debug Diagnostic Tool v1.2
Run program
Add Rule "Crash"
Select "Specific Process"
on page Advanced Configuration set your exception if you know on which exception it fails or just leave this page as is
Set userdump location
Now wait for process to crash, log file is created by DebugDiag. Now activate tab Advanced Analysis, select Crash/Hang Analyzers in top list and dump file in lower list and hit Start Analysis. This will generate html report for you. Hopes you found usefull info in that report. If you have problem with analyze, upload html report somewhere and place url here so we can focus on it.
My app does not invoke any native code, or use any unsafe blocks, or
even any non-CLS compliant types like uint
You may think this, but threading, synchronization via semaphore, mutex it any handles all are native. .net is a layer over operating system, .net itself does not support pure clr code for multithreading apps, this is because OS already does it.
Most likely this is thread synchronization error. Probably multiple threads are trying to access shared resource like file etc that is outside clr boundary.
You may think you aren't accessing com etc, but when you call certain API like get desktop folder path etc it is called through shell com API.
You have following two options,
Publish your code so that we can review the bottleneck
Redesign your app using .net parallel threading framework, which includes variety of algorithms requiring CPU intensive operations.
Most likely programs fail after certain period of time as collections grow up and operations fail to execute before other thread interfere. For example, producer consumer problem, you will not notice any problem till producer will become slower or fail to finish its operation before consumer kicks in.
Bug in clr is rare, because clr is very stable. But poorly written code may lead error to appear as bug in clr. Clr can not and will never detect whether the bug is in your code or in clr itself.
Did you run a memory test for your machine as the one time I had comparable symptoms one of my dimms turned out to be faulty (a very good memorytester is included in Win7; http://www.tomstricks.com/how-to-test-your-ram-or-memory-with-windows-memory-diagnostic-tool-in-windows-7/)
It might also be a heating/throttling issue if your CPU gets too hot after this period of time. Although that would happen sooner imho.
There should be a dumpfile that you can analyze. If you never did this find someone who did, or send that to microsoft
I will suggest you open a support case via http://support.microsoft.com immediately, as the support guys can show you how to collect the necessary information.
Generally speaking, like #paulsm4 and #psulek said, you can utilize WinDbg or Debug Diag to capture crash dumps of the process, and within it, all necessary information is embedded. However, if this is the very first time you use those tools, you might be puzzled. Microsoft support team can provide you step by step guidance on them, or they can even set up a Live Meeting session with you to capture the data, as the program crashes so often.
Once you are familiar with the tools, in the future you can perform similar troubleshooting more easily,
http://blogs.msdn.com/b/lexli/archive/2009/08/23/when-the-application-program-crashes-on-windows.aspx
BTW, it is too early to say "I've found a bug". Though you cannot obviously find in your program a dependency on native code, it might still have a dependency on native code. We should not draw a conclusion before debugging further into the issue.

How Does The RedGate Profiler Actually Work

It seems that the Ants profiler does instrumentation and sampling of code at exactly the same time which I find very interesting
I have used the VS profiler and you have to run two different profile sessions to identify bottlenecks - How does ANTS capture IO bound function calls without modifying and injecting code into the compiled functions?
EDIT: Does ants use instrumentation or sampling?
The Ants profiler offers several different profiling modes, some of which use sampling and some of which use instrumentation (the instrumentation modes are only available in the professional edition, and the sampling mode was introduced fairly recently). A brief description of the modes that are available is here, as well as a comparison between the different modes.
RedGate doesn't publish technical details about how their profiler works, but from experimentation I haven't found any significant differences from how other profilers work (just a different user interface, and I'm sure there are optimizations in some areas or fringe features that aren't available in other profilers). Based on your question I'm guessing you're somewhat familiar with other profilers, but if you're interested in how it works on a lower level, here's a brief overview:
In sampling mode, the profiler will periodically run OS interrupts to pause program execution, and checks what method the program is currently in. Every method in a binary or intermediate-language assembly consists of an instruction set. When a program is executed, every thread will progress along that instruction set, jumping to a different instruction set location when a method is invoked. The current location for the threads execution can be though of as a pointer to a location in this instruction set, and you can find out the address is for the instruction set for a given method. So a profiler builds a map of instruction set locations to method names, and when it pauses the program it checks where the current execution is. By mapping it to the method name, it can count the number of times that method has been invoked and how long it is taking to run. But since this is only a sample, there may be other methods that were called that we didn't notice because they returned before we paused the program in the next interval.
In instrumentation mode, the profiler will inject additional instructions into the program's instruction sets. Lets say you have an instruction set A->B->C that is invoked when the doSomething() method is called. A very crude profiler could inject additional instructions to do something like
long starttime = currentTime()
A
B
C
long endtime = currentTime() - starttime
this will tell you how much time it took to run the method. Of course, modern profilers do much more elaborate instructions than this to optimize performance, get performance on a per-line basis, get memory and IO information as well as timing information, etc, but the principle is the same.
Modern OSes also have a decent capability to get hardware-level diagnostics as well, so that profilers can get more detailed information about most of the systems, including memory, disk IO, CPU utilization, etc. How these different systems work are very device and driver specific.
Note that this injection can be done at various stages - on the source level, on the binary level before execution, at runtime, etc. Especially with languages like C#, where there is an intermediate stage between compilation and assembly execution (the CLR), it's easier to inject these additional instructions at runtime. It also allows you to surround methods within the internal .NET framework (such as the IO operations that I think you are asking about) with custom instructions at runtime, so that you can get performance information even if you don't have the original source code. This again relies on its ability to build a mapping from instruction sets to method names, but the difference is that you can still inject the additional instructions without having to resort to sampling. I think there are special precautions you can take to make this more difficult, but there's no real incentive for Microsoft to do this to the internals of the .NET framework.
If the Ants Profiler you are referring to is the one from RedGate then this is for .NET runtimes. I suspect that they are using the very extensive API for profiling applications, provided by Microsoft; I suggest you look for ICorProfilerCallback/2/3 and ICorProfilerInfo/2/3 for starters. The API allows for instrumentation and filtered callbacks for method entry/exit calls and other features.
Some open source (or code available) profilers of interest I suspect for you based on your query are CLRProfiler4 (Microsoft) and SlimTune.

IDisposable - automated check for using construct

Does anybody know of a way to automatically find any variable, where the type implements IDisposable but the using construct is not used?
ie. a way to check for potentially unreleased unmanaged resources?
Also, is it possible to see the number and types of resource held by a running application?
There's a code analysis rule for this:
http://msdn.microsoft.com/en-us/library/ms182289%28VS.100%29.aspx
This can be run from VS 2010 Premium or Ultimate or separately with FxCop:
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=917023f6-d5b7-41bb-bbc0-411a7d66cf3c
Another thing I've seen done is to capture a stack trace when an IDisposable object is constructed and then if the finalize is hit (meaning Dispose() was not called) log an error with the constructed stack trace. This is expensive so you may only want to do it in development, or only start collecting stack traces the second time your app runs into this problem (if you run into it once, you're most likely going to run into it many times within a single app execution). This method works for IDisposable instances that are longer lived (not just local variables). Of course it also only works for custom IDisposable objects since it requires custom code in the constructor/dispose/finalizer.
VS 2010 code analyzer's and FxCop? (not sure) Reliability Rules will do a pretty good job on detecting if there exists execution paths in the analyized code where objects implementing IDisposable are going out of scope without calling Dispsoe() (it is overeager and will in many ocasions detect false positives).
This will of course not enforce the using construct as a correctly implemented try-finally block will pass the test (both are obviously equivalent under the hood, so I'm not sure if thats an issue).
EDIT: FX Cop does not support this warning. Its availabe since VS 2005 code analyzer.

C# How to dump all variables & current values during runtime

Are there any in-built or 3rd party libraries that allow you to simply dump all variables in memory during run time? What I would like is to be able to view variables & current values similarly to viewing them by hitting a break point and hovering over variables, but without actually having to halt the program execution (i.e. just get a snapshot). Would be good if it could dump them to a file which can then be opened later in a program to get a nice GUI interface to view them, but simple text file dump would be good enough.
I can't think of an easy way to do this in a generic fashion. What could work is programmatically creating a dump file of your running process. You could either do this with P/Invoke to the dbghelp.dll routines or spawn a cdb.exe process to create the dump file. Once you have the file, you could open it up in a debugger for later analysis using SOS.dll with cdb.exe/windbg.exe, or even write a debugger script to dump the data you want (mostly) automatically.
I believe some sort of logging framework would help you to do that...
Check out:
http://www.dotnetlogging.com/
At my workplace we use log4net which works pretty well for us.
So how come you're wanting to dump out all the variables for later analysis? Have you considered writing your code test first so that you can reduce your reliance on the debugger and have a suite of automated test checking the values for you?
In the past I've used the YourKit .Net profiler in order to profile .Net applications.
While I've only ever used it to connect to running applications personally the Snapshot documentation does state that they have a Profiler API that can be used to programmatically dump snapshots for later review.
Code wise this looks to be as simple as the following:
Controller c = new Controller();
String snapshotPath = c.CaptureSnapshot();
I believe you can then load the snapshot files into the YourKit GUI at a later date to review them.
I would not be surprised if some of the other popular profilers like JetBrains dotTrace Performance and RedGates ANTS Performance Profiler have similar programmatic APIs but I couldn't quickly find obvious documentation on their websites (and I didn't want to watch their webinars to find out if this feature existed!)
For this you can use WMemoryProfiler to
Get all objects in all appdomains as an object array
Create a memory dump of your own process
Serialize specific objects to disc
To make this happen you need Windbg of course but the Api of WMemoryProfiler is fully managed and you can basically self debug your process. The library takes care of the usual debugger oddities since it does wrap Windbg in a nice accessible library.
The code below does get all instances of System.Threading.Thread objects into an object array. This way you can write a visualizer for your own application objects at runtime. The other overload does simply give you all objects in all AppDomains.
using (var debugger = new MdbEng())
{
var dummy = new Thread(() => {});
dummy.Name = "Dummy Thread";
// Get all thread objects in all AppDomains
var threads = debugger.GetObjects("System.Threading.Thread", true);
foreach (Thread t in threads)
{
Console.WriteLine("Managed thread {0} has Name {1}", t.ManagedThreadId, t.Name);
}
GC.KeepAlive(dummy);
}
Since it is a wrapper around Windbg you can also create a memory dump on the fly and later load a memory dump from your process to extract object data for visualization from the dump. Commerical Memory Profilers (e.g. MemoryProfiler from Scitech) employ this technique since years but it is quite slow when you have a huge memory dump since they are using also Windbg as dump analyzer.
You can try Intellitrace tool provided with ultimate version of visual studio. It is what you describe - it records what is happening in your app and allows you to debug it without executing your program with hovering over variables and all other debug windows to help you.
You can use PostSharp . I found it very useful to record debug times because of the environment application was deployed. And instrumented/recorded many things.
But obviously you'll need to specify all variables you need to record.
Check more details here.

Categories

Resources