*VERY* poor man’s profiler


There are tons of great .NET profilers out there, but my experince with customers is that very few are using them.  There are a varity of reasons for this, but if you are seroius about getting the best performance possible out of your managed apps you should be using one (or more) of them. 

 

But even if you are not super serois about the performance of your app, you should know what your app loads.   Here is a handy little tip Krzysztof used on a recent customer visit… I thought it was such a good idea, I’d share it with you. 

 

Just cut-and-paste this code into some steady state part of your app (on a button click, etc) and then read the log file it creates.  Do you know where all of those modules are coming from?  What benefit is your app getting from them?  Why are they there?

 

.NET Framework 2.0 code:

            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            foreach (System.Diagnostics.ProcessModule pm in System.Diagnostics.Process.GetCurrentProcess().Modules)

            {

                sb.AppendLine(pm.FileName);

            }

            System.IO.File.WriteAll(“C:\\ModulesLoadedLog.txt”, sb.ToString());

 

 

.NET Framework 1.0 and 1.1 code:

        System.Text.StringBuilder sb = new System.Text.StringBuilder();

        foreach (System.Diagnostics.ProcessModule pm in System.Diagnostics.Process.GetCurrentProcess().Modules)

        {

            sb.Append(pm.FileName + System.Environment.NewLine);

        }

        System.IO.StreamWriter sw = new System.IO.StreamWriter(“C:\\ModulesLoadedLog.txt”);

        sw.Write(sb.ToString());

        sw.Close();

 

(Note: the Observing a thing changes it principle does apply here. Do you know what modules the above code causes to be loaded?)

 

 

From a simple hello world app on V1.1 I get 25

D:\Documents and Settings\brada\Start Menu\Programs\Startup\foo.exe

D:\WINDOWS\system32\ntdll.dll

D:\WINDOWS\system32\mscoree.dll

D:\WINDOWS\system32\ADVAPI32.dll

D:\WINDOWS\system32\KERNEL32.dll

D:\WINDOWS\system32\RPCRT4.dll

D:\WINDOWS\system32\tsappcmp.dll

D:\WINDOWS\system32\msvcrt.dll

D:\WINDOWS\system32\SHLWAPI.dll

D:\WINDOWS\system32\GDI32.dll

D:\WINDOWS\system32\USER32.dll

D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll

D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\MSVCR71.dll

D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\fusion.dll

D:\WINDOWS\system32\ole32.dll

D:\WINDOWS\system32\SHELL32.dll

D:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.100.0_x-ww_8417450B\comctl32.dll

d:\windows\microsoft.net\framework\v1.1.4322\mscorlib.dll

d:\windows\assembly\nativeimages1_v1.1.4322\mscorlib\1.0.5000.0__b77a5c561934e089_a4297563\mscorlib.dll

D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorsn.dll

D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\MSCORJIT.DLL

d:\windows\assembly\gac\system\1.0.5000.0__b77a5c561934e089\system.dll

d:\windows\assembly\nativeimages1_v1.1.4322\system\1.0.5000.0__b77a5c561934e089_c7218c53\system.dll

D:\WINDOWS\system32\psapi.dll

 

And on V2.0 I get 20 (5 less!)

D:\Program Files\Microsoft Visual Studio 8\VC\foo.exe

D:\WINDOWS\system32\ntdll.dll

D:\WINDOWS\system32\mscoree.dll

D:\WINDOWS\system32\ADVAPI32.dll

D:\WINDOWS\system32\KERNEL32.dll

D:\WINDOWS\system32\RPCRT4.dll

D:\WINDOWS\system32\tsappcmp.dll

D:\WINDOWS\system32\msvcrt.dll

D:\WINDOWS\system32\SHLWAPI.dll

D:\WINDOWS\system32\GDI32.dll

D:\WINDOWS\system32\USER32.dll

D:\WINDOWS\Microsoft.NET\Framework\v2.0.41111\mscorwks.dll

D:\WINDOWS\Microsoft.NET\Framework\v2.0.41111\MSVCR80.dll

D:\WINDOWS\assembly\NativeImages_v2.0.41111_32\mscorlib\4b0ec1643e93f732a00f1ef4a3519a2a\mscorlib.ni.dll

D:\WINDOWS\system32\ole32.dll

D:\WINDOWS\system32\shell32.dll

D:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.100.0_x-ww_8417450B\comctl32.dll

D:\WINDOWS\Microsoft.NET\Framework\v2.0.41111\mscorjit.dll

D:\WINDOWS\assembly\NativeImages_v2.0.41111_32\System\f6276094994ff83d999dad8ef607a716\System.ni.dll

D:\WINDOWS\system32\psapi.dll

 

The log from the ScreenSaver that ships in the C# Express skus shows that I get 60+ modules loaded… Know what you are using…  

 

Comments (9)

  1. Did I count right? It is 24 in v1.1.

    20 dlls is still way too much for helloworld.

  2. RichB says:

    So, whereas .Net 1.1 loads the NGen’d image, plus the image in the GAC (for metadata), .Net v2 doesn’t load the image in the GAC.

    Does that mean that ngen’d images have all the metadata they need to execute? Does that mean that ngen’d images can be deployed without their original assembly?

  3. The answer is "No", of course.

    We still need the IL images to do native image validation. But we don’t load them anymore in Whidbey.

    Only things going through LoadLibrary will show up in the output. This is the limitation of psapi.dll APIs.

  4. Jelle Druyts says:

    Good point by RichB: where’d the original assemblies go? Or does the metadata get injected into the .text section of the PE/COFF file again?

    Other missing dll’s in v2: mscorsn.dll (got merged into mscorwks.dll) and fusion.dll. I suppose fusion.dll must have been merged into something else as well, I can’t imagine how you could load some of the listed modules without it 😉

    What I find peculiar is that despite it being a Console app (since System.Windows.Forms.dll isn’t loaded), it still needs Windows stuff like GDI32.dll and comctl32.dll.

    Regarding the Heisenberg question: what the code will *cause to be loaded* depends on the code that ran before it 😉 I don’t think it actually *needs* anything beyond the usual suspects (mscorlib, System.dll & friends) though… But I’m obviously wrong since you asked in the first place 🙂

  5. Ollie Riches says:

    Don’t you just love refactoring 🙂

    I always use a profiler now on projects, it has made my implementations in .Net much more efficient and I believe given me a better understanding of .Net and how you are meant to use framework….

    I am always surprised that developers don’t use them….

  6. Sam says:

    Ants is my favorite profiler, too bad I can’t afford to buy it for my wee pet projects :/

    Sam

  7. Brad Williams says:

    I’m not quite appreciating why it’s important in general to know what your app loads. What are some reasons? Thanks in advance.

  8. RJ says:

    In this case observing doesn’t have to change it. Just use one of the many tools that listis dlls in a process. Like Process Explorer from sysinternals.com. procexp even gives easy access to the .net perf counters for a process.

  9. Judah says:

    Are there any good profilers out there that work on the 2.0 beta? I love Red Gate’s Antz .NET profiler, given that it has per-line timing which is great. Unfortunately, they don’t have a beta that works on the 2.0 beta yet.