<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.microsoft.co.il/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Pavel&amp;#39;s Blog : ATL</title><link>http://blogs.microsoft.co.il/blogs/pavely/archive/tags/ATL/default.aspx</link><description>Tags: ATL</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>Writing a .NET Profiler</title><link>http://blogs.microsoft.co.il/blogs/pavely/archive/2008/05/20/writing-a-net-profiler.aspx</link><pubDate>Tue, 20 May 2008 13:36:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:90645</guid><dc:creator>pavely</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/pavely/rsscomments.aspx?PostID=90645</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/pavely/commentapi.aspx?PostID=90645</wfw:comment><comments>http://blogs.microsoft.co.il/blogs/pavely/archive/2008/05/20/writing-a-net-profiler.aspx#comments</comments><description>&lt;p&gt;I was recently asked how a managed application can know the&amp;nbsp;actual size of managed objects it allocates. Although there exists a &lt;strong&gt;Marshal.SizeOf&lt;/strong&gt; method&amp;nbsp;that seemingly can do the trick, this only works for value types, as the method is intended to be used in interop scenarios where some unmanaged memory must be allocated in managed code and passed to some unmanaged function. This question, and others like it can best be answered by using a the .NET profiling API.&lt;/p&gt;
&lt;p&gt;The .NET profiling API allows the (native C++) programmer to inject a DLL that can receive various events from the CLR during execution of a managed application. A .NET profiler does not only enable to &amp;quot;profile&amp;quot; an application, but also allows the code&amp;nbsp;to interrogate the CLR for various pieces of information, such as object size.&amp;nbsp;Interesting events&amp;nbsp;might be loading of an assmbly, starting/ending of a GC cycle, creation/destruction of AppDomain, and many others.&lt;/p&gt;
&lt;p&gt;To write such a profiler, one must use the .NET profiling API. What this means is writing a COM class that implements the &lt;font color="#010001"&gt;&lt;strong&gt;ICorProfilerCallback2 &lt;/strong&gt;interface, and meaningfully implementing the required methods for the interesting notifications. During the implementation&amp;nbsp;of the &lt;strong&gt;Initialize&lt;/strong&gt; method, the profiler code receives a pointer to the &lt;font color="#010001"&gt;&lt;strong&gt;ICorProfilerInfo2 &lt;/strong&gt;interface implemented by the CLR. The profiler should cache it and use in the notifications implementation to extract more info from the CLR.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;Also, in the &lt;strong&gt;Initialize &lt;/strong&gt;method, the code calls the CLR&amp;#39;s &lt;strong&gt;SetEventMask &lt;/strong&gt;method to indicate which events it wants to be notified. This is an optimization, so the CLR is not bothered with calling the profiler on every event, but only on the requested events.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;To install the profiler, the COM dll should be registered as all COM DLLs, using &lt;strong&gt;regsvr32.exe&lt;/strong&gt; (assuming, of course the DllRegisterServer function is in there. If you use the ATL library to write the COM DLL, then this is implemented for you).&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;Then, 2 environment variables must be set: &lt;strong&gt;COR_ENABLE_PROFILING=1&lt;/strong&gt; and &lt;strong&gt;COR_PROFILER=&amp;lt;progid or clsid of COM class&amp;gt;&lt;/strong&gt;. For example, the settings needed for tha attached sample profiler are:&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;&lt;strong&gt;set COR_ENABLE_PROFILING=1&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;&lt;strong&gt;set COR_PROFILER=SampleProfiler.Profiler&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;The scope of setting of these variables matters. If they are set in a dedicated command prompt, all .NET apps starting from that command prompt will be profiled.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;If they are set in user scope, then all .NET apps running from that user&amp;#39;s account are &amp;quot;profiled&amp;quot;, i.e. the DLL gets injected into the process. If the vars are set in system scope, all .NET apps are profiled.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;The profiler should transmit in some way the info it gathers to some repository or other listening app that can show the info in a meaningful way.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#010001"&gt;&lt;font color="#010001"&gt;I&amp;#39;ve attached a sample profiler that writes its info to a file to the c:\temp folder (so make sure this exists) as a simple log file just for demo purposes. It captures the timings of events such as start/end of GC, AppDomain creation/destruction and assembly loading. The coed is written with VS 2008 but can be written with any VS verstion. It uses ATL to create the required boilerplate COM code and just implements the necessary interface.&lt;/p&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=90645" width="1" height="1"&gt;</description><enclosure url="http://blogs.microsoft.co.il/blogs/pavely/attachment/90645.ashx" length="74685" type="application/x-zip-compressed" /><category domain="http://blogs.microsoft.co.il/blogs/pavely/archive/tags/_DE05DB05DC05DC05EA05_+_D405D905_-_D805E705_/default.aspx">מכללת הי-טק</category><category domain="http://blogs.microsoft.co.il/blogs/pavely/archive/tags/COM/default.aspx">COM</category><category domain="http://blogs.microsoft.co.il/blogs/pavely/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/pavely/archive/tags/CLR/default.aspx">CLR</category><category domain="http://blogs.microsoft.co.il/blogs/pavely/archive/tags/ATL/default.aspx">ATL</category><category domain="http://blogs.microsoft.co.il/blogs/pavely/archive/tags/.NET+Profiling+API/default.aspx">.NET Profiling API</category></item></channel></rss>