<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/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>Vance Morrison's Weblog : Perf</title><link>http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx</link><description>Tags: Perf</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Slides for a talk on Performance </title><link>http://blogs.msdn.com/vancem/archive/2009/07/21/slides-for-a-talk-on-performance.aspx</link><pubDate>Tue, 21 Jul 2009 18:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9843454</guid><dc:creator>vancem</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/vancem/comments/9843454.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=9843454</wfw:commentRss><description>&lt;P&gt;&amp;nbsp;I am giving a .NET Performance talk for the users group at the Royal Bank of Canada, and I am posting the slides for the talk here for future reference.&amp;nbsp; (see power point document attached to this entry below).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;Anyone who has heard me speak will see recognise the themes:&amp;nbsp; Good perf does not just happen, you have to plan, and to plan you have to measure.&amp;nbsp; I touch very briefly on some ways of measuring (Stopwatch, MeasureIt, XPerf)&lt;/P&gt;
&lt;P&gt;As with all talks, the goal is not so much to teach something, but rather to MOTIVATE you to learn more.&amp;nbsp;&amp;nbsp; Thus I want it to be very easy to follow up on the topics I so briefly touched upon.&amp;nbsp;&amp;nbsp; Thus I have pulled the bibliography out of the deck and placed it here so you can quickly research more. &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Articles&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://msdn.microsoft.com/en-us/magazine/cc301131.aspx" mce_href="http://msdn.microsoft.com/en-us/magazine/cc301131.aspx"&gt;Vance Morrison's MSDN articles&lt;/A&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://www.acm.org/ubiquity/views/v7i24_fallacy.html" mce_href="http://www.acm.org/ubiquity/views/v7i24_fallacy.html"&gt;The Fallacy of Premature Optimization (Randall Hyde, ACM.org)&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa292152(VS.71).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa292152(VS.71).aspx"&gt;MSDN Performance: Designing Distributed Applications&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://www.panopticoncentral.net/archive/2004/02/10/270.aspx" mce_href="http://www.panopticoncentral.net/archive/2004/02/10/270.aspx"&gt;The Ten Rules of Performance&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ms998530.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms998530.aspx"&gt;Improving .NET Application Performance and Scalability&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Blogs&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://blogs.msdn.com/vancem/default.aspx" mce_href="http://blogs.msdn.com/vancem/default.aspx"&gt;Vance Morrison's Weblog&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://blogs.msdn.com/ricom/default.aspx" mce_href="http://blogs.msdn.com/ricom/default.aspx"&gt;Rico &lt;/A&gt;&lt;A href="http://blogs.msdn.com/ricom/default.aspx" mce_href="http://blogs.msdn.com/ricom/default.aspx"&gt;Mariani's&lt;/A&gt;&lt;A href="http://blogs.msdn.com/ricom/default.aspx" mce_href="http://blogs.msdn.com/ricom/default.aspx"&gt; Performance Tidbits&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://blogs.msdn.com/clrperfblog/default.aspx" mce_href="http://blogs.msdn.com/clrperfblog/default.aspx"&gt;&lt;FONT color=#0000ff&gt;CLR and Framework &lt;/FONT&gt;&lt;/A&gt;&lt;A href="http://blogs.msdn.com/clrperfblog/default.aspx" mce_href="http://blogs.msdn.com/clrperfblog/default.aspx"&gt;&lt;FONT color=#0000ff&gt;Perf&lt;/FONT&gt;&lt;/A&gt;&lt;A href="http://blogs.msdn.com/clrperfblog/default.aspx" mce_href="http://blogs.msdn.com/clrperfblog/default.aspx"&gt;&lt;FONT color=#0000ff&gt; Blog&lt;/FONT&gt;&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://blogs.msdn.com/pigscanfly/archive/2008/02/09/xperf-a-new-tool-in-the-windows-sdk.aspx" mce_href="http://blogs.msdn.com/pigscanfly/archive/2008/02/09/xperf-a-new-tool-in-the-windows-sdk.aspx"&gt;Xperf&lt;/A&gt;&lt;A href="http://blogs.msdn.com/pigscanfly/archive/2008/02/09/xperf-a-new-tool-in-the-windows-sdk.aspx" mce_href="http://blogs.msdn.com/pigscanfly/archive/2008/02/09/xperf-a-new-tool-in-the-windows-sdk.aspx"&gt; Blog&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&amp;nbsp;Tools&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://blogs.msdn.com/vancem/archive/2009/02/06/measureit-update-tool-for-doing-microbenchmarks.aspx" mce_href="http://blogs.msdn.com/vancem/archive/2009/02/06/measureit-update-tool-for-doing-microbenchmarks.aspx"&gt;MeasureIt&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;A href="http://msdn.microsoft.com/en-us/performance/default.aspx" mce_href="http://msdn.microsoft.com/en-us/performance/default.aspx"&gt;Xperf&lt;/A&gt;&lt;A href="http://msdn.microsoft.com/en-us/performance/default.aspx" mce_href="http://msdn.microsoft.com/en-us/performance/default.aspx"&gt; performance analysis tool&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;I did not have time to more than just mention it, but I want to emphasize here that Event Tracing for Windows (ETW) and its viewer (XPERF), is the most useful general purpose tool for doing performance analysis on windows, period.&amp;nbsp;&amp;nbsp;&amp;nbsp; It is well worth investing time&amp;nbsp;in learning about it more.&amp;nbsp;&amp;nbsp;&amp;nbsp; Currently it has some limitations associated with&amp;nbsp;diagnosing managed code, however rest assured that we are addressing these issues.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&amp;nbsp;An important take away here is that&amp;nbsp;learning about XPERF is a great investment.&amp;nbsp;&amp;nbsp; It is THE tool that the entire Windows team uses for all of its&amp;nbsp;performance diagnosis, and we are investing in it for the future too.&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; FONT-SIZE: 11pt; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9843454" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/vancem/attachment/9843454.ashx" length="233361" type="application/vnd.openxmlformats-officedocument.pres" /><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category></item><item><title>Slides for our All Day PDC 2008 talks on: Performance By Design </title><link>http://blogs.msdn.com/vancem/archive/2008/10/30/slides-for-our-all-day-pdc-2008-talks-on-performance-by-design.aspx</link><pubDate>Thu, 30 Oct 2008 07:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9023656</guid><dc:creator>vancem</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/vancem/comments/9023656.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=9023656</wfw:commentRss><description>&lt;P&gt;Every&amp;nbsp;year or so,&amp;nbsp;when Microsoft&amp;nbsp;believes it has something useful to say to develoeprs it&amp;nbsp;hosts a&amp;nbsp;Programmer Developer's Conference.&amp;nbsp;&amp;nbsp;It is doing so this year from 10/27 through 10/30.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Between&amp;nbsp;Rico Marani, Mark Friedman and myself, we gave a all day talk on writing high performance software for the .NET Runtime.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;I am posting the slides here for reference.&amp;nbsp;&amp;nbsp; I had to break the slides up into the sessions we gave them to fit within the size restrictions of the blog.&amp;nbsp; I also had to post them as seperate posting (since the blog software seems to only support one attachment per blog entry).&amp;nbsp;&amp;nbsp; However I have put the quick links to them here.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A id=bp___v___ctl00_ctl00_bcr_r___postlist___EntryItems_ctl02_Attachment___DownLoadLink href="http://blogs.msdn.com/vancem/attachment/9023614.ashx" minmax_bound="true"&gt;&lt;FONT color=#0033cc&gt;PerfByDesign.Intro.pptx&lt;/FONT&gt;&lt;/A&gt; - talk given by Rico Mariani on the importance of thinking about performance early in the design cycle. &lt;/LI&gt;
&lt;LI&gt;&lt;A id=bp___v___ctl00_ctl00_bcr_r___postlist___EntryItems_ctl05_Attachment___DownLoadLink href="http://blogs.msdn.com/vancem/attachment/9023599.ashx" minmax_bound="true"&gt;PerfByDesign.CPU.pptx&lt;/A&gt; talk given by&amp;nbsp;me on measuring time (particularly CPU time).&amp;nbsp; I talk about MeasureIt here.&lt;/LI&gt;
&lt;LI&gt;&lt;A id=bp___v___ctl00_ctl00_bcr_r___postlist___EntryItems_ctl04_Attachment___DownLoadLink href="http://blogs.msdn.com/vancem/attachment/9023602.ashx" minmax_bound="true"&gt;&lt;FONT color=#0033cc&gt;PerfByDesign.Memory.pptx&lt;/FONT&gt;&lt;/A&gt;&amp;nbsp; talk given by me on measuring memory in managed applications (Good Stuff)&lt;/LI&gt;
&lt;LI&gt;&lt;A id=bp___v___ctl00_ctl00_bcr_r___postlist___EntryItems_ctl03_Attachment___DownLoadLink href="http://blogs.msdn.com/vancem/attachment/9023609.ashx" minmax_bound="true"&gt;PerfByDesign.Parallel.pptx&lt;/A&gt; talk given by me on using our new Parallel Extentions Framework (PFX) to&amp;nbsp;exploit multi-procs.&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A id=bp___v___ctl00_ctl00_bcr_r___postlist___EntryItems_ctl01_Attachment___DownLoadLink href="http://blogs.msdn.com/vancem/attachment/9023627.ashx" minmax_bound="true"&gt;PerfByDesign.aspnet.pptx&lt;/A&gt; talk given by Mark Friedman on tuning ASP.NET applications. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;These slides are of course more useful to those who actually attended the talks, however I think there is a lot that can be learned from them even without having heard us talk.&amp;nbsp; I am happy to answer any questions that anyone might have after viewing the slides.&lt;/P&gt;
&lt;P&gt;You can view the other talks and slides from the PDC by going to there web site &lt;A href="http://microsoftpdc.com/Agenda/"&gt;http://microsoftpdc.com/Agenda/&lt;/A&gt;.&amp;nbsp;&amp;nbsp;This will certainly work for those attending the PDC, but might work for everyone (I don't really know). &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9023656" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/.NET+Architecture/default.aspx">.NET Architecture</category></item><item><title>Slides for PDC 2008 Talk: Performance By Design: Measuring CPU Time</title><link>http://blogs.msdn.com/vancem/archive/2008/10/30/slides-for-pdc-2008-talk-performance-by-design-measuring-cpu-time.aspx</link><pubDate>Thu, 30 Oct 2008 07:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9023599</guid><dc:creator>vancem</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/vancem/comments/9023599.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=9023599</wfw:commentRss><description>&lt;P&gt;These are the slides for the talk I gave on 10/26/2008 at the Programmer Developer Converence (PDC) on the basics of performance investigation &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9023599" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/vancem/attachment/9023599.ashx" length="385513" type="application/vnd.openxmlformats-officedocument.pres" /><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/.NET+Architecture/default.aspx">.NET Architecture</category></item><item><title>Links to MSDN articles I have written on designing for performance</title><link>http://blogs.msdn.com/vancem/archive/2008/10/22/links-to-msdn-articles-i-have-written-on-designing-for-performance.aspx</link><pubDate>Wed, 22 Oct 2008 17:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9011163</guid><dc:creator>vancem</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/vancem/comments/9011163.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=9011163</wfw:commentRss><description>&lt;P&gt;I just happen to notice that I don't have any links from my blog to some recient MSDN articles I wrote on performance.&amp;nbsp;&amp;nbsp; I want to quickly correct his with this posting.&lt;/P&gt;
&lt;P&gt;There is actually a very nice summary page that MSDN created that gathers together all the articles I have written over time.&amp;nbsp; The link is &lt;A class="" href="http://msdn.microsoft.com/en-us/magazine/cc301131.aspx" mce_href="http://msdn.microsoft.com/en-us/magazine/cc301131.aspx"&gt;here&lt;/A&gt; (a web search of MSDN Vance Morrison will also turn it up).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;The two articles I want to call your attention to however are these&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/magazine/cc500596.aspx" mce_href="http://msdn.microsoft.com/en-us/magazine/cc500596.aspx"&gt;CLR Inside Out: Measure Early and Often for Performance, Part 1&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/magazine/cc507639.aspx" mce_href="http://msdn.microsoft.com/en-us/magazine/cc507639.aspx"&gt;CLR Inside Out: Measure Early and Often for Performance, Part 2&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;These articles are about how most perf problems start very early in the design, and that there is no substitute for knowing how much things cost when doing your design.&lt;/P&gt;
&lt;P&gt;There is a nice companion tool that I wrote callled 'MeasureIt' which you get download (free), that allows you to&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Get a bunch of useful benchmarks on how much various .NET operations cost&lt;/LI&gt;
&lt;LI&gt;Measure other stuff that you happen to be interested in easily (eg how fast is that collection class you are using?)&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;In fact, I intend I just recently used MeasureIt to measure how expensive the various levels of the CPU cache hierarchy are.&amp;nbsp;&amp;nbsp; (that is how much does a fetch from L1 cost?&amp;nbsp; How much if you miss the L1 Cache but hit the L2 cache?&amp;nbsp; How much&amp;nbsp;more expensive is it when you miss both L1 and L2 and have to go to main memory?).&amp;nbsp;&amp;nbsp; If there is interest I can write a quick blog about that.&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9011163" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/Tools/default.aspx">Tools</category></item><item><title>Giving Performance Talk at Programmer Developers Conference (PDC) 10/26</title><link>http://blogs.msdn.com/vancem/archive/2008/09/25/giving-performance-talk-at-programmer-developers-conference-pdc-10-26.aspx</link><pubDate>Thu, 25 Sep 2008 19:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8965246</guid><dc:creator>vancem</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/vancem/comments/8965246.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=8965246</wfw:commentRss><description>&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;This&amp;nbsp;is a quick plug for a pre-conference session I am giving on 10/26 at Microsoft’s &lt;A href="http://www.microsoftpdc.com/Agenda/Preconference.aspx" mce_href="http://www.microsoftpdc.com/Agenda/Preconference.aspx"&gt;Programmer Developers Conference&lt;/A&gt; (PDC) 10/26 held this year in Los Angeles.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;My talks are part of a all day session that I am giving along with &lt;A href="http://blogs.msdn.com/ricom/"&gt;Rico Mariani&lt;/A&gt; and Mark Friedman entitled&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-ALIGN: center" align=center&gt;&lt;FONT face=Calibri size=3&gt;Performance by design using the .NET Framework&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=Calibri size=3&gt;In the morning Rico will be starting us off with some basics: having a performance budget, designing for performance and the basic of measuring.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Mark will speak on the performance characteristics of important parts of the framework.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;In the afternoon, I will be doing two sessions, the first is on memory performance in .NET:&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;when you should care, how to measure it, behavior of the GC, and best practices.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;I will follow up on multi-threading performance in .NET.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This session will overlap a bit with the talk on multi-core programming, but I will focus on the .NET aspects only try to have a very practical perspective.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Finally Mark will finish off with two talks, one on ASP.NET performance, and another on Silverlight performance.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;FONT face=Calibri size=3&gt;I am looking forward to it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;If you are interested, you can learn more about registration &lt;/FONT&gt;&lt;A href="http://www.microsoftpdc.com/Agenda/Preconference.aspx"&gt;&lt;FONT face=Calibri size=3&gt;here&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;I am also interested in talking to customers and getting feedback, so if you want to talk to someone who has been on the .NET Runtime team 'forever', come to the PDC and we can talk.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8965246" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/.NET+Architecture/default.aspx">.NET Architecture</category></item><item><title>To Inline or not to Inline: That is the question</title><link>http://blogs.msdn.com/vancem/archive/2008/08/19/to-inline-or-not-to-inline-that-is-the-question.aspx</link><pubDate>Wed, 20 Aug 2008 06:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8880541</guid><dc:creator>vancem</dc:creator><slash:comments>19</slash:comments><comments>http://blogs.msdn.com/vancem/comments/8880541.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=8880541</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;In a &lt;A href="http://blogs.msdn.com/vancem/archive/2008/05/12/what-s-coming-in-net-runtime-performance-in-version-v3-5-sp1.aspx" mce_href="http://blogs.msdn.com/vancem/archive/2008/05/12/what-s-coming-in-net-runtime-performance-in-version-v3-5-sp1.aspx"&gt;previous posting&lt;/A&gt;, I mentioned that &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=AB99342F-5D1A-413D-8319-81DA479AB0D7&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=AB99342F-5D1A-413D-8319-81DA479AB0D7&amp;amp;displaylang=en"&gt;.NET V3.5 Service Pack 1&lt;/A&gt; had significant improvements in the Just in time (JIT) compiler for the X86 platform, and in particular its ability to inline methods was improved (especially for methods with value type arguments).&amp;nbsp;&amp;nbsp; Well now that this release is publically available my claim can be put to the test.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;In fact a industrious blogger named &lt;A href="http://www.cuttingedge.it/blogs/steven"&gt;Steven&lt;/A&gt; did just that and blogged about it &lt;A href="http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=40#body"&gt;here&lt;/A&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;What he did was to create a series of methods each a bit bigger than the previous one, and determined whether they got inlined or not.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Steven did this by throwing an exception and then programmatically inspecting the stack trace associated with the exception.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;This makes sense when you are trying to automate the analysis, but for simple one-off cases, it is simpler and more powerful to simply look at the native instructions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;See &lt;A href="http://blogs.msdn.com/vancem/archive/2006/02/20/535807.aspx" mce_href="http://blogs.msdn.com/vancem/archive/2006/02/20/535807.aspx"&gt;this blog&lt;/A&gt; for details on how to using Visual Studio.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;What Steven found was that when tried to inline the following method&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public void X18(int a)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;if (a &amp;lt; 0 || a == 100)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Throw(a * 2);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;It did not inline.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This was not what Steven expected, because this method was only 18 bytes of IL.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The previous version of the runtime would inline methods up to 32 bytes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;It seems like the JIT’s ability to inline is getting worse, not better.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;What is going on? &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Well, at the heart of this anomaly is a very simple fact: &lt;B style="mso-bidi-font-weight: normal"&gt;It is not always better to inline&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Inlining always reduces the number of instructions executed (since at a minimum the call and return instructions are not executed), but it can (and often does), make the resulting code bigger.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most of us would intuitively know that it does not make sense to inline large methods (say 1Kbytes), and that inlining very small methods that make the call site smaller (because a call instruction is 5 bytes), are always a win, but what about the methods in between?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Interestingly, as you make code bigger, you make it slower, because inherently, memory is slow, and the bigger your code, the more likely it is not in the fastest CPU cache (called L1), in which case the processor stalls 3-10 cycles until it can be fetched from another cache (called L2), and if not there, in main memory (taking 10+ cycles).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For code that executes in tight loops, this effect is not problematic because all the code will ‘fit’ in the fastest cache (typically 64K), however for ‘typical’ code, which executes a lot of code from a lot of methods, the ‘bigger is slower’ effect is very pronounced.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Bigger code also means bigger disk I/O to get the code off the disk at startup time, which means that your application starts slower.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;In fact, the first phase of the JIT inlining improvement was simply to remove the restrictions on JIT inlining.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;After that phase was complete we could inline A LOT, and in fact the performance of many of our ‘real world’ benchmarks DECREASED.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Thus we had irrefutable evidence that inlining could be BAD for performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We had to be careful; too much inlining was a bad thing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Ideally you could calculate the effect of code size on caching and make a principled decision on when inlining was good and bad.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, the JIT compiler has does not have enough information to take such a principled approach.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;However some things where clear&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;1.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;If inlining makes code smaller then the call it replaces, it is ALWAYS good.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that we are talking about the NATIVE code size, not the IL code size (which can be quite different).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;The more a particular call site is executed, the more it will benefit from inlning.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thus code in loops deserves to be inlined more than code that is not in loops.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;3.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;If inlining exposes important optimizations, then inlining is more desirable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In particular methods with value types arguments benefit more than normal because of optimizations like this and thus having a bias to inline these methods is good.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Thus the heuristic the X86 JIT compiler uses is, given an inline candidate. &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;1.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Estimate the size of the call site if the method were not inlined.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Estimate the size of the call site if it were inlined (this is an estimate based on the IL, we employ a simple state machine (Markov Model), created using lots of real data to form this estimator logic)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;3.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Compute a multiplier.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;By default it is 1 &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;4.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Increase the multiplier if the code is in a loop (the current heuristic bumps it to 5 in a loop)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;5.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;Increase the multiplier if it looks like struct optimizations will kick in. &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;6.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;If InlineSize &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&amp;lt;= NonInlineSize * Multiplier do the inlining.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;What this means is that by default, only methods that do not grow the call site will be inlined, however if the code is in a loop, it can grow as much as 5x &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;What does this mean for Steven’s test?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;It means that simple tests based solely on IL size are not accurate.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;First what is important is the Native size, not the IL size, and more importantly, it is much more likely to be inlined if the method is in a loop. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;In particular, if you modify Steven’s test so that the methods are in a loop when they are called, in fact all of his test methods get inlined.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;To be sure, the heuristics are not perfect.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The worse case is a method that is too big to be inlined, but is still called A LOT (it is in a loop) and calls other small methods that COULD be inlined but are not because they are not in a loop.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The problem is that the JIT does not know if the method is called a lot or not, and by default does not inline in that case. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;We are considering adding an attribute to a method which gives a strong hint that the method is called a lot and thus would bump the multiplier much like if there was a loop, but this does not exist now.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;We definitely are interested in feedback on our inlining heuristic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If Steven or anyone else finds real examples where we are missing important inlining opportunities we want to know about them, so we can figure out whether we can adjust our heuristics (but please keep in mind that they are heurisitics.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They will never be perfect).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8880541" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/.NET+Architecture/default.aspx">.NET Architecture</category></item><item><title>What's Coming in .NET Runtime Performance in Version V3.5 SP1</title><link>http://blogs.msdn.com/vancem/archive/2008/05/12/what-s-coming-in-net-runtime-performance-in-version-v3-5-sp1.aspx</link><pubDate>Tue, 13 May 2008 02:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8497943</guid><dc:creator>vancem</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/vancem/comments/8497943.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=8497943</wfw:commentRss><description>&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;SPAN style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT size=4&gt;&lt;FONT color=#4f81bd&gt;&lt;FONT face=Cambria&gt;What's Coming in .NET Runtime Performance in Version V3.5 SP1&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;It certainly has been a while since I last blogged.&amp;nbsp;&amp;nbsp; Most of this is laziness on my part, but I can truthfully say that it is partly because I have been busy trying to get the next servicing release of the .NET framework (called Version 3.5 Service Pack 1) out the door.&amp;nbsp;&amp;nbsp;&amp;nbsp; Part of the framework (runtime + libraries) servicing is an updated version of the runtime DLL (which we call the CLR).&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;How do you know if you have an updated CLR?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;If the file&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l2 level1 lfo1"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;c:\windows\microsoft.net\Framework\V2.0.50727\mscorwks.dll &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;has a version number greater than 50727.3000 then you have the changes I will be talking about.&amp;nbsp;&amp;nbsp; Because this is just a servicing of the runtime, we had to confine ourselves to changes that we felt had a very low chance of breaking existing applications.&amp;nbsp;&amp;nbsp; Nevertheless we were able to add substantial performance value.&amp;nbsp;&amp;nbsp; There are two changes I would like to talk about in particular.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Improved Cold Startup performance&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;A href="http://blogs.msdn.com/vancem/archive/2007/04/09/a-model-for-cold-startup-time-of-an-application-on-windows.aspx"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Cold startup&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt; time is the time it takes an application to start when all the data needed to run has to be fetched from disk (rather than from the operating system disk cache).&amp;nbsp; The second time an application starts (Warm startup) is substantially faster because&amp;nbsp;very few (slow)&amp;nbsp;disk reads are needed to get&amp;nbsp;the application running.&amp;nbsp;&amp;nbsp;&amp;nbsp;It is not unusual for the&amp;nbsp;warm startup time to be good (&amp;lt; 1 sec), but&amp;nbsp;for the cold startup time to be&amp;nbsp;quite bad (5-10 sec).&amp;nbsp;&amp;nbsp;In the new runtime we go to a lot of effort to pack all the&amp;nbsp;code and runtime structures (for now only in DLLS associated with the framework itself), to reduce the&amp;nbsp;amount of Disk I/O needed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;While the improvements benefit all code that uses the framework, it helps the most on code that has been precompiled using &lt;/SPAN&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/6t9t5wcf(VS.80).aspx"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt"&gt;NGEN.exe&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt; and the effect is more pronounced on larger applications.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo3"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Inlining&amp;nbsp;of value&amp;nbsp;types (C# structs).&amp;nbsp; (X86)&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;C# structs are what the .NET runtime calls value types.&amp;nbsp; They are called this because when you have fields or arrays of such data structures, the value is embedded directly in the field (not referenced through a pointer).&amp;nbsp;&amp;nbsp;&amp;nbsp; All the primitive types (int, char, bool) are value types, as well as a few types defined in the base class library like DateTime, Decimal, Point and Rectangle.&amp;nbsp;&amp;nbsp;&amp;nbsp; The previous version of the code generator (for X86) did almost no optimization on value types.&amp;nbsp;&amp;nbsp; This was unfortunate, because although value types are not common (most types are classes, not structs), when they are used, they can be used heavily, and so optimization is important.&amp;nbsp; In fact the biggest single piece of feedback we got on our &lt;/SPAN&gt;&lt;A href="https://connect.microsoft.com/VisualStudio/feedback"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt"&gt;feedback site&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt; related to performance was concerning more &lt;/SPAN&gt;&lt;U&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt"&gt;agressive inlining of value type methods&lt;/SPAN&gt;&lt;/U&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;.&amp;nbsp;&amp;nbsp;&amp;nbsp; The runtime’s 64 bit code generators could already optimize value types, but the code generator for X86 could not.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Since X86 is still the dominate platform there was an unmet need.&amp;nbsp;&amp;nbsp;&amp;nbsp; In this servicing we included the work we did to enable this for X86.&amp;nbsp;&amp;nbsp;&amp;nbsp; Your own code often may not benefit from this improvement (because it does not use value classes much), but if you do use them, you tend to use them heavily, and the value could be substantial.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt"&gt;64 Bit machines: X64&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Much of the cold startup work was rearranging the data in precompiled framework executables to pack heavily used items together, and as such is applies equally well for 64 bit platforms like X64.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;However there are places where 64 bit machines are quite different (how exceptions are delivered by the operating system) and we did not invest heavily in tuning (packing) these places.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The result is that cold startup wins will not be as dramatic on 64 bit machines.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;There were improvements to the 64 bit code generator, but since this code generator could already inline value types, we did not need to do work in that specific area.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt"&gt;64 Bit machines: Intel Itanium &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-bidi-font-weight: bold"&gt;Most users of the .NET runtime run it on the X86 processor, however beginning with Version 2.0 of the runtime also supports the Intel &lt;/SPAN&gt;&lt;A href="http://en.wikipedia.org/wiki/Itanium"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-bidi-font-weight: bold"&gt;Itanium&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-bidi-font-weight: bold"&gt; architecture.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;In fact, internally the Itanium version of the runtime came on line well before the X64 version did.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The Itanium processor tends to be used in high end server applications, where scalability is a great concern.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;In the next major release of the Framework, we are continuing to investigate and improve our performance on the Itanium architecture.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Microsoft is a charter member of the &lt;/SPAN&gt;&lt;A href="http://www.itaniumsolutions.com/alliance"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-bidi-font-weight: bold"&gt;Itanium Solutions Alliance (ISA)&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-bidi-font-weight: bold"&gt; and we are excited to work with the other members of ISA to further enhance the performance of the .NET Framework on Intel Itanium Architecture.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Check out the &lt;A class="" href="http://blogs.msdn.com/clrperfblog/archive/2008/05/13/investigating-framework-performance-on-itanium-rudimentary-considerations.aspx" mce_href="http://blogs.msdn.com/clrperfblog/archive/2008/05/13/investigating-framework-performance-on-itanium-rudimentary-considerations.aspx"&gt;CLR Performance Team’s blog on investigating Itanium perf&lt;/A&gt;&amp;nbsp; for more on this work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8497943" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category></item><item><title>Assumptions used in the cold startup formula (when is it accurate). </title><link>http://blogs.msdn.com/vancem/archive/2007/04/15/assumptions-used-in-the-cold-startup-formula-when-is-it-accurate.aspx</link><pubDate>Sun, 15 Apr 2007 18:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2145396</guid><dc:creator>vancem</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/vancem/comments/2145396.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=2145396</wfw:commentRss><description>&lt;P&gt;After my &lt;A class="" title="Cold startup formula" href="http://blogs.msdn.com/vancem/archive/2007/04/09/a-model-for-cold-startup-time-of-an-application-on-windows.aspx" mce_href="http://blogs.msdn.com/vancem/archive/2007/04/09/a-model-for-cold-startup-time-of-an-application-on-windows.aspx"&gt;last blog entry on cold startup &lt;/A&gt;a reader (&lt;A id=ctl00___ctl00___ctl00_ctl00_bcr_ctl00___Comments___Comments_ctl02_NameLink title=dimkaz href="http://blogs.msdn.com/utility/Redirect.aspx?U=http%3a%2f%2fspaces.msn.com%2fmembers%2fdimkaz%2f" minmax_bound="true"&gt;dimkaz&lt;/A&gt;) worried that the formula would not be accurate in many cases.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;This topic is worth discussing in some detail because it pretty common to apply formulas outside&amp;nbsp;the assumptions&amp;nbsp;implicit in them,&amp;nbsp;and simply get wrong conclusions.&amp;nbsp; The most fundamental part of the formula is &amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Cold Startup = WarmStartup + DiskIOTime&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Technically this is only accurate if WarmStarup time and DiskIOTime don't overlap in time.&amp;nbsp; For example, if DiskIOTime and WarmStartup time could be done completely concurrently then ColdStartup time would be the maximum, not the sum of the two times, which could be quite different.&amp;nbsp; &amp;nbsp; So the question is how much overlap is there between the disk and the CPU?&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Well in one very common case the answer is simple.&amp;nbsp; If the application only has one thread of execution (eg. you did not use System.Thread, or System.Threadpool in your startup path), and you don't do any significant explicit file I/O in your application on startup, then the times will be additive (the formula above is correct).&amp;nbsp; In this very common scenario, the vast majority of disk time is time spent fetching the program itself from the disk.&amp;nbsp; The operating system does this by doing what is called 'demand paging'.&amp;nbsp; The idea is that in one operation (the API is called LoadLibrary), the entire file is read into memory, however all the data is not actually read in at that time, but is done 'lazily' on demand.&amp;nbsp; Basically whenever the CPU tries to access memory that was supposed to be read in, but is not actually been read in, the OS takes a 'hard page fault', stops what it is doing and fetches the needed page from disk (on x86 this happens pages are 4096 bytes).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The upshot of this is that during cold startup the CPU is constantly trying to access some new part of the program which needs to be paged in (it takes a hard page fault).&amp;nbsp; Each time&amp;nbsp;it has to stop, and get data from the disk.&amp;nbsp;&amp;nbsp;Since it&amp;nbsp;really needs that data (typically the next instruction to executed) to proceed, so it simply has to wait until the I/O is done.&amp;nbsp; Thus&amp;nbsp;there is no overlap between the CPU and disk I/O for that thread of execution.&amp;nbsp; Hard page faults typically take 4-8msec to service, which translate into 8 to 16 million instructions on a 2Ghz machine (so a hard page fault is&amp;nbsp;quite significant), which h is why cold startup times can easily be many seconds long.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;It is possible that if there were multiple threads of execution during startup, that while one thread is waiting for I/O to complete it can be doing something useful on another thread (thus CPU and I/O can overlap), so this may invalidate the formula above, however as we will see, the even in this case the windows prefecher keeps the formula working.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Even single threaded programs might&amp;nbsp;be able to overlap I/O and CPU if they do a lot of explicit, sequential&amp;nbsp;file reads during startup.&amp;nbsp; The reason is that when a Stream.Read is executed the operating system knows that&amp;nbsp;the program is very likely to want to continue reading even after it has return the data that is actually requested.&amp;nbsp; Thus it issues the&amp;nbsp;disk requests to prefech the next chunks&amp;nbsp;of&amp;nbsp;data from the disk&amp;nbsp;and allows the&amp;nbsp;disk to fetch them while the program operates on the last chunk that it was given.&amp;nbsp; If&amp;nbsp;the program does a lot of computation and&amp;nbsp;explicit&amp;nbsp;sequential reads, then the CPU tends to completely overlap the I/O and the formula is wrong (it is too pessimistic).&amp;nbsp;&amp;nbsp; This can happen for example in compilers, where allot of explicit reads as done as well as lot of computation (although even there, the bulk of the computation happens later, after all the data is read in, and thus does not overlap with I/O). &lt;/P&gt;
&lt;P&gt;Finally there is one more interesting case of overlap.&amp;nbsp; In the formula above all disk I/O is assumed to not overlap with itself.&amp;nbsp; This is correct if there is only one disk involved, but if multiple disks are involed obviously overlap is likely to happen.&amp;nbsp;&amp;nbsp; Thus the formula is for the 1-disk case and is only an upper bound for the mulit-disk case.&amp;nbsp;&amp;nbsp; In practice, few applications have control over the hardware configuration of the system, and in fact most client machines have only one disk, so the formula covers what is likely to be the most interesting case, but the assumption should be called out.&lt;/P&gt;
&lt;P&gt;The upshot is that the formula is valid for programs single threaded programs that don't do allot of sequential file I/O.&amp;nbsp; It is an upper bound for all programs, and frankly, tends to be pretty accurate even in those cases, because events tend to conspire to prevent CPU and I/O from overlapping effectively. &lt;/P&gt;
&lt;P&gt;In my next blog I will talk about the windows prefetcher, which is some very cool technology that has been in the OS since windows XP, and happens to make the cold startup formula accurate for pretty much any program.&amp;nbsp; &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2145396" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category></item><item><title>A Model for cold startup time of an application on Windows.  </title><link>http://blogs.msdn.com/vancem/archive/2007/04/09/a-model-for-cold-startup-time-of-an-application-on-windows.aspx</link><pubDate>Mon, 09 Apr 2007 07:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2058151</guid><dc:creator>vancem</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/vancem/comments/2058151.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=2058151</wfw:commentRss><description>&lt;P&gt;Well it is has been a while.&amp;nbsp;&amp;nbsp;&amp;nbsp; I see now that it is been getting close to 1/2 a year since I last posted.&amp;nbsp;&amp;nbsp; Sigh.&amp;nbsp;&amp;nbsp;It is so easy for other things to get busy and not to blog.&amp;nbsp;&amp;nbsp; I have resolved to try to be a bit more methodical about and insure that I write something every week or so.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;Over the past year I have been doing quite a bit of work with the Common Language runtime trying to improve its cold startup time.&amp;nbsp;&amp;nbsp; This has been a common complaint, and we knew when we shipped version 2.0 of the runtime that there was a lot we could do.&amp;nbsp;&amp;nbsp; Unfortunately, it may be a while before the wider world see the benefit of this work (our ship cycle is quite long, and the next public release of the runtime has no major changes to the 'core' part of the runtime that I work on).&amp;nbsp;&amp;nbsp; Nevertheless, I learn some useful things so far in this work and I thought I would write some of them down. &lt;/P&gt;
&lt;P&gt;&amp;nbsp;When we first seriously looked at cold startup time we had two problems&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Our measurements of cold startup were VERY noisy.&amp;nbsp; This makes work quite difficult.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;We did not have a clear idea how to prioritize work.&amp;nbsp; We knew Disk I/O was important, but how important?&amp;nbsp; Were disk seeks or data transfer time most important?&amp;nbsp; We needed to have a good model of what contributed to cold startup time before we could come up with an attack plan and prioritize the work properly.&amp;nbsp; &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;The good news is that we came up with simple&amp;nbsp;model that we are pretty happy with that helped solve both of these problem that I would like to share with you.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;First: What is cold startup time?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Cold startup time is defined to be the time it takes an application to start up (be responsive to user input), on a machine that has just been rebooted.&amp;nbsp;&amp;nbsp; The important characteristic of cold startup time is that any data on the disk (mostly the program itself), needs to be read off the disk because it is not in the operating system 's disk cache.&amp;nbsp;&amp;nbsp; Thus cold startup has a very strong component of Disk I/O time associated with this data fetch.&amp;nbsp; In contrast, warm startup time is defined as application startup time on second launch.&amp;nbsp;&amp;nbsp; Under normal circumstances warm startup has almost NO disk I/O because literally everything the program needs is in cache, and thus the program never needs to go to disk to get anything.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;This leads to a very nice formula&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;ColdStartup = WarmStartup + DiskIOTime&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;This formula is accurate to a very good approximation.&amp;nbsp;&amp;nbsp; Moreover DiskIOTime can be broken into two parts:&amp;nbsp; The time it takes to move the disk head and for the disk to rotate so that the correct data is under the head (Seek Time), and the time it takes to actually transfer the data.&amp;nbsp;&amp;nbsp; Thus&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;DiskIOTime = DiskSeekTime + DiskDataTransferTime.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;These quantities can also be modeled well.&amp;nbsp; Disk Seek time does depend on how far the disk head needs to travel, however disks are now quite large (100s of Gig), and the Operating system does try to keep files that are used together close together on the disk (More on that on a later blog if there is interest), so the amount of head movement is typically very small as a % of the total possible disk travel.&amp;nbsp;&amp;nbsp; Moreover, whenever there is ANY movement of the disk head, it takes a significant amount of time for the head to 'settle' so that an accurate read can happen.&amp;nbsp; Thus to a good approximation, the seek time is independent of how far the disk head moves, and thus can be accurate modeled by a constant.&amp;nbsp;&amp;nbsp; Some empirical data gathering shows that for the machines that we typically use this time was about 4msec per movement.&amp;nbsp; Thus&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&amp;nbsp;DiskSeekTimeMsec = NumberOfSeeks * 4&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The DiskTransferTime can also be accurately be modeled.&amp;nbsp; It is completely determined by the rotational speed of the disk, the number of read heads, and the density of the bits on the disk (all of which are constant for a given disk).&amp;nbsp;&amp;nbsp; Typical disks that we use give about 50MBytes / sec transfer speeds.&amp;nbsp; This means that it takes&amp;nbsp;1/50 of a second (20 msec) to transfer&amp;nbsp;1MByte of data.&amp;nbsp;&amp;nbsp; Thus&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;DiskTransferTimeMsec = NumberMBytes * 20&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Putting this all together gives the&amp;nbsp;formula &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;ColdStartupTimeMSec&amp;nbsp;= WarmStartupTimeMsec + 4 * NumberOfReads + 20 * NumberMBytes&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;This formula shows that you can attach cold startup one of three ways:&amp;nbsp; Either reduce the warm startup time (computations done at startup by the app), the number of data read from the disk (typically dominated by the amount of UNIQUE code used at startup), or the number of disk reads (typically by packing the&amp;nbsp;code&amp;nbsp;used in the startup path&amp;nbsp;so that it is all&amp;nbsp;together&amp;nbsp;and can be read from the disk in one read).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Now the formula does depend on disk technology, but typically will not vary in huge ways (by more than a factor of 2) from one disk to another (assuming a certain quality in your hardware).&amp;nbsp;&amp;nbsp;&amp;nbsp; In fact one of the nice benefits of the formula is that it is MACHINE INDEPENDENT (assuming the warm startup time is hardware independent (at least approximately)).&amp;nbsp; Thus measurements on one hardware can be compared to that on different hardware (you can't do that with time).&amp;nbsp;&amp;nbsp; Effectively the formula calculates the cold startup time on a theoretical piece of hardware (that happens to have the specs of the machine I used to derive the 4 msec and 20 msec/MB numbers.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;This solved&amp;nbsp;both of our original problems (noise and prioritizing dev work).&amp;nbsp;&amp;nbsp;The main reason cold startup is noisy&amp;nbsp;is that the disk&amp;nbsp;is being shared by&amp;nbsp;ALL apps in the&amp;nbsp;system, and thus their activity can perturb the time.&amp;nbsp; However&amp;nbsp;the operating system already tracks the metrics above (number of read I/O&amp;nbsp;and the number of I/O bytes), and breaks it down PER PROCESS, which means&amp;nbsp;these I/O measurements have NO NOISE associated with other processes activity.&amp;nbsp; This is GREAT and reduces the noise SUBSTANTIALLY.&amp;nbsp; &amp;nbsp; It solved the prioritizing problem because it tells us the first level of breakdown of what contributes to cold startup and thus we know which one more dominate for a given scenario (typically none of the terms can be ignored), and thus where we can get the best benefit (for a given cost).&lt;/P&gt;
&lt;P&gt;Next time I will talk about how these numbers play out in a real scenario, and where that led us to work prioritization.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;Its good to be back!&lt;/P&gt;
&lt;P&gt;Vance&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2058151" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category></item><item><title>Drilling into .NET Runtime microbenchmarks:  'typeof' optimizations. </title><link>http://blogs.msdn.com/vancem/archive/2006/10/01/779503.aspx</link><pubDate>Sun, 01 Oct 2006 16:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:779503</guid><dc:creator>vancem</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/vancem/comments/779503.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=779503</wfw:commentRss><description>&lt;P&gt;&lt;FONT size=2&gt;In my &lt;A href="http://blogs.msdn.com/vancem/archive/2006/09/21/765648.aspx"&gt;last blog entry &lt;/A&gt;showed how to use a simple simle class called MultiSampleCodeTimer to measure the performance (time), of pretty much any fragment of CLR code quickly and easily.&amp;nbsp; That entry had a solution packaged up as a zip file &lt;A href="http://blogs.msdn.com/vancem/attachment/765648.ashx"&gt;TypePerfMeasurement.zip&lt;/A&gt; that you could use to duplicate the experiment yourself.&amp;nbsp;&amp;nbsp; However I did not have time to show you what is particularly interesting about those paricular performance measurements (I pciked them for a reason).&amp;nbsp; Here I wish to do complete the explaination.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;When I unpack and run &lt;A href="http://blogs.msdn.com/vancem/attachment/765648.ashx"&gt;TypePerfMeasurement.zip &lt;/A&gt;(please do it yourself, detailed instructions at the end of my &lt;A href="http://blogs.msdn.com/vancem/archive/2006/09/21/765648.aspx"&gt;last post&lt;/A&gt;), I get the following output.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=1&gt;Data units of msec resolution = 0.279365 usec
10 typeof(string)                       : count: 10000    7.677 +- 3%    msec
10 typeof(string).TypeHandle            : count: 10000    0.000 +- &amp;gt;400% msec
10 anObj.GetType() == type              : count: 10000    7.393 +- 41%   msec
10 Type.GetTypeHandle(obj).Equals(tHnd) : count: 10000    4.554 +- 9%    msec
10 anObj.GetType() == typeof(string)    : count: 10000    0.103 +- 7%    msec
10 (anObj is string)                    : count: 10000    0.594 +- 12%   msec
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT size=2&gt;Please take the time to run it yourself.&amp;nbsp; You don't need Visual studio do so (see readme.txt file, it is as easy as running 'buildit, and running the resulting exe).&amp;nbsp; Note that if you are running under visual studio, and you get very differrent numbers based on whether you run it under VS or outside VS, you did not set your VS settings as I describe in &lt;A href="http://blogs.msdn.com/vancem/archive/2006/02/20/535807.aspx"&gt;this post&lt;/A&gt;.&amp;nbsp; Go and do that now.&amp;nbsp; Note that your numbers are going to be different than mine, but the relative sizes between the various rows should be reasonably close.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;What do these numbers mean?&amp;nbsp;&amp;nbsp; We need some background first.&amp;nbsp;&amp;nbsp; The .NET Runtime defineds a type called System.Type, which is a representation of&amp;nbsp;a type in the system.&amp;nbsp; EVERY class that has been defined in the system has a cooresponding System.Type.&amp;nbsp; The System.Type object is the gateway to exploring at runtime all the data that the users typed when he defined the type.&amp;nbsp; You can get superclasses, methods, properties fields, etc by calling the appropriate operations on System.Type.&amp;nbsp;&amp;nbsp; This ability to inspect and invoke characteristics of the source code is called Reflection, and System.Type is your gateway into this capability.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;While the System.Type class is very powerful, that power comes at a cost.&amp;nbsp; Also most programs doe NOT need this power and should NOT use it (I need to blog about that too) becuase of the perf cost. &amp;nbsp; Thus the .NET runtime has tried to provide alternatives to using System.Type for some common operations that CAN be implemented efficiently.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;One such operation is testing if an object is of a EXACTLY a certain type.&amp;nbsp; While the 'is' operator in c# can often be used for this (and is the preferred method), however that mechanism will also match any subtype (eg ("foo" is object) returns true) and also only works for literal types (if the type was a variable of type System.Type), you could not do this.&amp;nbsp;&amp;nbsp; For example&lt;/FONT&gt;&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=1&gt;    System.Type myType = typeof(string); // in real life not a literal
    // and then in other methods (and maybe in a loop)
    if (anObj.GetType() == myType) { /* some op */ }
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT size=2&gt;In this example we use the 'GetType() method on System.Object to see if 'anObject' is a string.&amp;nbsp;&amp;nbsp; Unfortunately both the operations used above (typeof, and GetType()), are relatively expensive (as shown in my data above 5-10ms instead of .7ms &amp;nbsp;for 'is' operator).&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Type checking operations like the one above are common enough that the .NET runtime has added a special&amp;nbsp;type called 'RuntimeTypeHandle' to make them fast.&amp;nbsp; RuntimeTypeHandle is a less user friendly but 'fast' alternative to System.Type.&amp;nbsp; It happens to be simply a managed wrapper that represents the internal pointer (to a structure called a &amp;nbsp;MethodTable), that the runtime uses internally to represent a type.&amp;nbsp; As mentioned it is not very friendly, however it can handle the scenario above, and is very fast.&amp;nbsp;&amp;nbsp; The code using RuntimeTypeHandles looks like&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=1&gt;    RuntimeTypeHandle myType = typeof(string).TypeHandle;
    // and then in other methods (and maybe in a loop)
    if (Type.GetTypeHandle(anObj).Equals(myType)) { /* some op */ }
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT size=2&gt;This code is significantly faster than the previous code becuse no System.Type object needed to be created, only RuntimeTypeHandles, wich is simply a value type wrapping an unmanaged poitner, and thus is very lean (The code above sadly is slower than it should be because some JIT optimizations where not done in time for V2.0, but is still&amp;nbsp;significantly faster than using&amp;nbsp;System.Type.&amp;nbsp;&amp;nbsp; The first operation &lt;/FONT&gt;&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=1&gt;    RuntimeTypeHandle myType = typeof(string).TypeHandle;
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT size=2&gt;Is blazenly fast, as shown by our measurements (it is slow small it is in the noise).&amp;nbsp; This is suprising because this line does a 'typeof(string)' and we know that that operation is relatively&amp;nbsp; slow.&amp;nbsp; Setting a breakpoint in this code shows why.&amp;nbsp; That line of code compiled down to &lt;/FONT&gt;&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=1&gt;    00000000&amp;nbsp; mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dword ptr [ecx+10h],790FA3E0h 
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT size=2&gt;Basically the JIT compiler is smart enough to realize that to fetch the RuntimeTypeHandle, you don't need to fetch the System.Type and fetch its TyepHandle, you can just lookup the value at compile time and emit code to generate the literal.&amp;nbsp; This is very fast.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Sadly the other part of the operation&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=1&gt;    if (Type.GetTypeHandle(anObj).Equals(myType)) { /* some op */ }&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT size=2&gt;Should be just as fast (fetch the MethodTable poitner from the the object, and test for pointer equality), but is not due to some JIT optimizations that did not kick in appropriately (you will see that we make real calls for both GetTypeHanlde and Equals).&amp;nbsp;&amp;nbsp; Even so, it is faster because we avoid creating a System.Type object.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;As data point of just how fast the code above coudl be (when the JIT is fixed), consider the final experiment in the code&lt;/P&gt;&lt;PRE&gt;    result = anObj.GetType() == typeof(string);
&lt;/PRE&gt;
&lt;P&gt;Given what we know already, we would expect this to be slow, and yet, the measurements above show it to be FASTER than using the 'is' opertator.&amp;nbsp; How can that be?&amp;nbsp;&amp;nbsp; The answer is that the JIT recognises this sequence and knows that while it seems like two System.Type object need to be created and compared, all you really want is a yes-no answer on a type question that can be answered using RuntimeTypeHandles.&amp;nbsp; It thus substitutes that code&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=1&gt;    0000000f&amp;nbsp; cmp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dword ptr [edx],790FA3E0h &lt;BR&gt;    00000015&amp;nbsp; sete&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; al&amp;nbsp;&amp;nbsp; &lt;BR&gt;    00000018&amp;nbsp; mov&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte ptr [ecx+0Ch],al 
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;FONT size=2&gt;EDX holds 'anObj' and the method table for an object is the first field of the object, and 790fa3e0h is the method table pointer&amp;nbsp;(RuntimeTypeHandle) for string.&amp;nbsp; (See previous post on using !DumpMT to determine this).&amp;nbsp;&amp;nbsp; Thus in one instrution we have tested whether 'anObj' is string.&amp;nbsp; The 'sete' instruction converts the procressor condition flags set by 'cmd' into a boolena value in register AL, and the last insturction sets 'result' to this value.&amp;nbsp; This is pretty lean an mean!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT size=3&gt;Summary:&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;In this entry, we have taken a look at some code generation for doing 'type reflection'.&amp;nbsp; We measured its performance and got some anomolies (some operations were much faster than we expected.&amp;nbsp;&amp;nbsp; We looked into the disassembly for those operations and determined that the JIT compiler was doing some non-trivial optimizations that made certain operations very fast (in one case faster than&amp;nbsp;the&amp;nbsp;'built in' 'is' operation).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We have learned that a System.Type object is relatively expensive compared to RuntimeTypeHandle, and we have used techniques from the last few &lt;A href="http://blogs.msdn.com/vancem/archive/category/10837.aspx"&gt;perf blog entries &lt;/A&gt;to help dig into exactly why.&lt;/P&gt;
&lt;P&gt;I again encourage you to experiment with the &lt;A href="http://blogs.msdn.com/vancem/attachment/765648.ashx"&gt;TypePerfMeasurement.zip &lt;/A&gt;example yourself and hone your skills in measuring and investigating .NET Runtime performance.&amp;nbsp; In my next blog entry I will be doing 'inventory' on the performance characteristics of the 'basic' operations of the runtime. &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=779503" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category></item><item><title>Measuring managed code quickly and easiliy: CodeTimers</title><link>http://blogs.msdn.com/vancem/archive/2006/09/21/765648.aspx</link><pubDate>Fri, 22 Sep 2006 06:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:765648</guid><dc:creator>vancem</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/vancem/comments/765648.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=765648</wfw:commentRss><description>&lt;P&gt;My performance blog entries to date have been 'foundational'.&amp;nbsp; In entries so far, I talk about how to use Visual Studio to look at the native code generated for the runtime.&amp;nbsp;&amp;nbsp; With this foundation, we can now start exploring what the native code for managed code looks like and what optimzations the runtime does on your behalf. &lt;/P&gt;
&lt;P&gt;However before we do that, we need one more foundational piece.&amp;nbsp; You really can't do performance work, without measuring, and so we need tools to help us measure.&amp;nbsp;&amp;nbsp; The simplest of these is the stopwatch.&amp;nbsp;&amp;nbsp; Thankfully Version 2.0 of the rutnime provides a nice, high resolution class that does this called System.Diagnostics.Stopwatch, which is ideal for measuring short intervals accurately.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;As nice as System.Diagnositcs.Stopwatch is, I found myself wanting more.&amp;nbsp; I was repeatingly typing code to start and stop the Stopwatch, subtracting the difference, subracting out the harness overhead, and doing statistics on the resulting numbers.&amp;nbsp;&amp;nbsp;&amp;nbsp; This led me to write two classes to automate this, call CodeTimer, and MultiSampleCodeTimer.&amp;nbsp;&amp;nbsp; I have included the source for these in the Zip file below.&amp;nbsp; Simply open it, copy the directory to your local drive, and open the .SLN file using visual studio.&amp;nbsp;&amp;nbsp; You can even compile the code without having Visual Studio.&amp;nbsp; Simply run the buildIt.bat&amp;nbsp;batch file&amp;nbsp; The only prerequisite&amp;nbsp;is that you need V2.0 of the .NET runtime installed (available from windows update, among other places).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The basic usage pattern for CodeTimer is&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;PRE&gt;    CodeTimer timer&amp;nbsp;= new CodeTimer();
    timer.Measure("Measurement Name", delegate {
       // Code that you want to measure
    }); 
&lt;/PRE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Basically I am making use the 'anonymous delegate' feature of c# to allow the client to specify the code that he wants measured inline.&amp;nbsp; One of the nice feature of anonymous delegates is that they 'capture' any local variables that are in scope.&amp;nbsp; Thus you can write things like&lt;/P&gt;&lt;PRE&gt;   
    CodeTimer timer&amp;nbsp;= new CodeTimer();
    string myString = "aString";
    string outString;
    timer.Measure("Measurement Name", delegate {
       outString = myString + myString;  // measuring concatination.  
    }); 
&lt;/PRE&gt;
&lt;P&gt;To measure the time it takes to concatinate two strings.&amp;nbsp; What is actually going on 'under the hood' is that the C# compiler generates a class with two fields 'myString' and 'outString' (a field for every local variable referenced in the body of the delegate code). An instance of this class is created and initialized to the values of locals and this object is used to create a delegate to&amp;nbsp;pass to 'Measure'.&amp;nbsp; Thus the locals are 'captured' and passed to the code that 'Measure' will&amp;nbsp;ultimately call.&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;This detail is imortant if you are measuring very small operations, because field access generates different code than local variable access.&amp;nbsp;&amp;nbsp; Thus in the example above, I am not just measuring string concatination, but also fetching an instance field (mystring) twice, and setting an instance field (outstring).&amp;nbsp;&amp;nbsp; Generally these fetches are small, and so they don't purturb the data much, but you should be aware of them.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;When you are measuring very short times (like the case above), you are likely to wan to run the test in a loop.&amp;nbsp; CodeTimer has built-in support for this.&amp;nbsp;&amp;nbsp; I can run the example above 1000 times in a loop by doing &lt;/P&gt;&lt;PRE&gt;   
    CodeTimer timer&amp;nbsp;= new CodeTimer(&lt;FONT color=#ff0000&gt;1000&lt;/FONT&gt;);
    string myString = "aString";
    string outString;
    timer.Measure("Measurement Name", delegate {
       outString = myString + myString;  // measuring concatination.  
    }); 
&lt;/PRE&gt;
&lt;P&gt;Which tells 'timer' to run any measurment 1000 times.&amp;nbsp; This is great for measuring micro-operations.&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;While 'CodeTimer' is great, I want still more.&amp;nbsp; I don't want just one sample, but 10 or more, so I can take the average and standard deviation and understand how 'noisy' my data is.&amp;nbsp; That is exactly what MulitSampleCodeTimer does.&amp;nbsp;&amp;nbsp; What is nice is that only the defintion of timer changes.&amp;nbsp; &lt;/P&gt;&lt;PRE&gt;   
    &lt;FONT color=#ff0000&gt;MultiSampleCodeTimer timer&amp;nbsp;= new MultiSampleCodeTimer(10, 1000);&lt;/FONT&gt;
    string myString = "aString";
    string outString;
    timer.Measure("Measurement Name", delegate {
       outString = myString + myString;  // measuring concatination.  
    }); &lt;/PRE&gt;
&lt;P&gt;Which asks that the code be run 1000 times per measurment and that 10 measurments be taken and used to compute min, max, mean, median and standard deviation.&amp;nbsp; The results are then printed (we are reallly starting to add value).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I find I use MultiSampleCodeTimer alot.&amp;nbsp;&amp;nbsp; I use it in the'TypePerfMeasurement' project below to measure the speed of some reflection type constructs.&amp;nbsp;&amp;nbsp; More on that in my next blog entry.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SUMMARY:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;In this blog entry, I have introduced to two classes 'CodeTimer' and 'MultiSampleCodeTimer' that can be used to meause the performance (time), of a wide variety of code.&amp;nbsp; You are encouraged to open, copy and build the attached sample below (you don't need VS to do it just the .NET runtime), and try it for yourself.&amp;nbsp;&amp;nbsp; Measuring performance has never been easier. &lt;/P&gt;
&lt;P&gt;Next time we will talk about the numbers that the TypePerfMeasurement experiment actually produce and talk about why the performance is the way it is.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;HOW TO USE THE DEMO:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I want my blogs to be 'hands-on' which means that there should always be something you can do after reading to experiement with the concept I talked about (that is there is homework!).&amp;nbsp; To make this easy I have attached a ZIP file that is a archive of a Visual Studio Solution for code to experiement with.&amp;nbsp; Note that you do NOT Need Visual Studio to compile and run the demo, so don't let that stop you.&amp;nbsp; To unpack this simply&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Click&amp;nbsp;on the ZIP file attachement at the&amp;nbsp;bottom of the post.&amp;nbsp; This will bring up a dialog asking if you wish to open the file.&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Click on the 'Open'&amp;nbsp;button.&amp;nbsp;&amp;nbsp; This will bring up&amp;nbsp;an explore window&amp;nbsp;displaying the contents of the ZIP file, which is a single directory.&amp;nbsp; If you just want to look at files, you can browse the files directly from this window.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;Open&amp;nbsp;a target folder on your local computer.&amp;nbsp; This can be anywhere, but if you have Visual Studio installed 'My Documents\Visual Studio 2005\Projects' is a good place&lt;/LI&gt;
&lt;LI&gt;Drag the directory from the ZIP file window into the target folder.&amp;nbsp; This copies the directory and all its contents to the local hard drive.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;Once copied, you can close the ZIP window, and click into the target directory.&amp;nbsp; There you will find a .SLN file, which you can double click on to bring up the solution in visual studio.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;If you don't have Visual Studio, you can still build the solution, there is a one line batch file called 'buildIt.bat' file that does this (it simply turns around and calls MSBuild to do its work).&amp;nbsp; You&amp;nbsp;do need Version 2.0 of the .NET Framework installed.&amp;nbsp; If you don't have it you can get it&amp;nbsp;from &lt;A href="http://www.windowsupdate.com"&gt;www.windowsupdate.com&lt;/A&gt; (custom downloads), or &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5&amp;amp;displaylang=en"&gt;here&lt;/A&gt;.&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;All the samples build and run and do something interesting 'out of the box',&amp;nbsp; They are meant to be easy to understand, commented,&amp;nbsp;samples so start looking around and experimenting (Hitting F10 to start stepping into the code is a good place to start).&amp;nbsp; &lt;/LI&gt;&lt;/OL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=765648" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/vancem/attachment/765648.ashx" length="11847" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/Tools/default.aspx">Tools</category></item><item><title>Low-Lock Techniques in action: Implementing a Reader-Writer lock</title><link>http://blogs.msdn.com/vancem/archive/2006/03/28/563180.aspx</link><pubDate>Tue, 28 Mar 2006 18:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:563180</guid><dc:creator>vancem</dc:creator><slash:comments>17</slash:comments><comments>http://blogs.msdn.com/vancem/comments/563180.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=563180</wfw:commentRss><description>&lt;P&gt;In my article &lt;SPAN class=MsoHyperlink&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: windowtext; FONT-FAMILY: Verdana; TEXT-DECORATION: none; text-underline: none"&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/05/08/Concurrency/default.aspx"&gt;What Every Dev Must Know About Multithreaded Apps&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt; I discuss the fundamental principles of using locks correctly.&amp;nbsp; In that article I strongly encourage the use of reader-writer locks&amp;nbsp;because these locks create the protection you need (insuring that readers and writers don't conflict), while potentially allowing significantly more concurrency to take place (by allowing multiple readers to enter the lock simultaneously).&amp;nbsp;&amp;nbsp;&amp;nbsp; I did not have space in that article to discuss reader-writer locks in detail however.&amp;nbsp; I would like to start correcting that here. &lt;/P&gt;
&lt;P&gt;The .NET Runtime implementation of a reader-writer lock is System.Threading.ReaderWriterLock.&amp;nbsp; It is really a pretty simple API at its heart (ignore stuff about LockCookies, it is there to support nesting of locks, which you should probably avoid anyway).&amp;nbsp; Here is a sample use&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P&gt;MyReaderWriterLock myLock = new MyReaderWriterLock();&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;myLock.AcquireReaderLock(Timeout.Infinite);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// No writers can be in here (AquireWriterLock will block)&lt;BR&gt;myLock.ReleaseReaderLock();&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;myLock.AcquireWriterLock(Timeout.Infinite);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// No readers or other writers can be in here (Aquire*Lock blocks)&lt;BR&gt;myLock.ReleaseWriterLock();&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;It is pretty straightforward to convert a program from using ordinary locks into using reader-writer locks (for those blocks that only read use AcquireReaderLock, otherwise use AquireWriterLock).&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;This is all very nice.&amp;nbsp; Unfortunately, there is a problem.&amp;nbsp; The current .NET Runtime implementation of ReaderWriterLock is about 8 times slower than System.Monitor (normal locks), in the common case where there is no lock contention.&amp;nbsp;&amp;nbsp; This is quite unfortunate, as it acts as a disincentive for doing the right thing (and using reader-writer locks).&amp;nbsp; Microsoft is likely to fix this in the next release, however what do you do in the mean time?&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Implementing a Reader-Writer Lock&lt;/STRONG&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;The obvious answer is to implement an efficient 'drop in' version of ReaderWriterLock that you can use until Microsoft provides an better one.&amp;nbsp; This is what this article is all about.&amp;nbsp; Sadly, if&amp;nbsp;our goal is to be as efficient as System.Montor, we can't use the standard locking protocol&amp;nbsp;to implement a Reader-Writer Lock since&amp;nbsp;every operation would have to lock and unlock, making it at least twice as slow as System.Monitor.&amp;nbsp; Thus we are forced to look into 'Low Lock Techniques', for an answer.&amp;nbsp; &amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;In my article &lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/default.aspx"&gt;Understand the Impact of Low-Lock Techniques in Multithreaded Apps&lt;/A&gt;&amp;nbsp;I list the techniques that &lt;EM&gt;&lt;SPAN style="FONT-FAMILY: Verdana"&gt;if used very carefully&lt;/SPAN&gt;&lt;/EM&gt;, can sometimes be applied to do very efficient multi-threaded synchronization.&amp;nbsp; I also mention that these techniques should only be used when the use of standard locks are problematic (usually because of performance issues).&amp;nbsp; Reader-Writer locks fall into this problematic cataegory.&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: black"&gt;Possible Low lock techniques to use&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;In the article the techniques are listed in order of decreasing utility, and are &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL type=1&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;Avoid locks on reads&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt; 
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;Spin Locks&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt; 
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;Raw Interlocked operations&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt; 
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo1; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;Lazyinit&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;Because the important APIs for a reader-writer lock always do an update, technique 1 is not applicable.&amp;nbsp; Thus our best bet is Spin locks (note the later two techniques are not NEARLY as useful as the first two).&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: black"&gt;Implementing a spin locks&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;It turns out that spin locks have some very nice properties.&amp;nbsp; Namely they ARE locks,&amp;nbsp;so all the nice properties of locks apply (once you take the lock you have mutual exclusion and reasoning about the program gets&amp;nbsp;MUCH easier).&amp;nbsp; They are also efficient (one interlocked operation per Enter-Exit pair).&amp;nbsp;&amp;nbsp;Thus we should be able to implement a Reader-writer lock with only one interlocked operation per method call, which is the same as System.Monitor (which also has one interlocked operation per method call).&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Verdana"&gt;Please refer to the code attached to this post &lt;A href="/vancem/attachment/563180.ashx"&gt;readerWriterDemo.cs&lt;/A&gt;.&amp;nbsp;&amp;nbsp;The first class is the spin lock.&amp;nbsp; It has an 'Enter' and 'Exit' API.&amp;nbsp; For more information on spin locks&amp;nbsp;see my low-lock article or Jeff Richter's article &lt;/SPAN&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/05/10/ConcurrentAffairs/"&gt;Concurrent Affairs&lt;/A&gt;.&amp;nbsp; The implementation in &lt;A href="/vancem/attachment/563180.ashx"&gt;readerWriterDemo.cs&lt;/A&gt; deals with all the subtle details you need to worry about.&amp;nbsp; It might need some tuning on how long it spins, but otherwise it is a very respectable implementation and you should feel free to use it if you need a spin lock yourself.&amp;nbsp;&amp;nbsp; The&amp;nbsp;only caveat I curretly have&amp;nbsp;is that I have&amp;nbsp;commented out calls to Thread.BeginCriticalRegion and Thread.EndCriticalRegion because they are relatively expensive (they make my perf numbers look bad), and&amp;nbsp;is only needed in environments like SQL Server where threads may be aborted at any instant.&amp;nbsp; If a thread is aborted while the spin lock is held, the SQL Server host&amp;nbsp; wants to know so that it can kill the entire appdomain instead of just the thread.&amp;nbsp;&amp;nbsp; If you are not in&amp;nbsp;SQL Server you can get away without this.&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;Before using the spin lock, we need to confirm that our read-writer lock is a good candidate for its use.&amp;nbsp; To be a good candidate is must be the case that the time the lock is held is very short (measured in at most dozens of instructions).&amp;nbsp;&amp;nbsp; We believe that this is the case since all of our API for the reader-writer lock do little and are perf critical, so the code paths NEED to be short.&amp;nbsp; However after we get our implementation we need to confirm that we don't have rare paths that might hold the lock for a long time.&amp;nbsp; It turns out with a bit of work we can make certain this is the case.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: black"&gt;Implementing a reader-writer lock with the spin lock &lt;/SPAN&gt;&lt;/STRONG&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;With a spin lock in hand, writing the reader-writer lock is not too much code (~ 150 lines, with comments), and hopefully is easy to understand.&amp;nbsp; Every API takes a lock, does work, and leaves.&amp;nbsp; To deal with the case where you must wait, we need OS structures to wait on (eg ManualResetEvent, AutoResetEvent).&amp;nbsp;&amp;nbsp; When a ManualResetEvent is 'Set' all threads waiting will wake up.&amp;nbsp; This is appropriate for readers.&amp;nbsp; For writers, it makes more sense to only wake up the first thread, and this is what AutoResetEvent does.&amp;nbsp;&amp;nbsp; The code has a lot of comments, so please take a look.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; There are actually a lot of subtleties to think about (what happens in various error conditions, what APIs can fail, how efficient the lock is in various scenarios, how long we are holding the spin lock ...).&amp;nbsp; I point out some of these subtleties in comments, however the really important point is that the code itself is short and straightforward.&amp;nbsp; This is CRITICAL because the more code you have, the more difficult it is to confirm the code works in all the subtle cases.&amp;nbsp; It pays to keep things simple.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: black"&gt;Performance Results of the reader-writer lock&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;If you run the program, it will measure the performance of an Enter/Exit pair.&amp;nbsp; Here is what I got.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN style="FONT-SIZE: 7.5pt"&gt;10Meg Enter/Exit&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 371.6953 msec = 59.61 CPU clocks per Enter/Exit&lt;BR&gt;10Meg RW Locks (.NET library) 3175.8594 msec = 8.5X monitor time&lt;BR&gt;10Meg New RW Locks&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 428.8234 msec = 1.2X monitor time&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As you can see, on my machine, the .NET library is 8.5X slower than System.Monitor, but the new RW locks are only&amp;nbsp;20% slower.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;With some more tuning I suspect&amp;nbsp;I can get even closer,&amp;nbsp;however it will make the code more complicated, so I don't want to do that in this published code (cleanliness is worth something).&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;As written, the lock has the property that if a writer is waiting for the locks, new readers can't come in and block it indefinitely.&amp;nbsp; Instead the readers wait until all the other readers drain, and the writer gets its turn.&amp;nbsp; The lock is unfair in the sense that when a lock is released it is not guaranteed that the first waiter gets the lock.&amp;nbsp;&amp;nbsp; Thus starvation is possible (however unlikely).&amp;nbsp; It turns out that fairness causes performance issues (I will discuss in a later blog), so the current unfair protocol has better performance characteristics in almost all cases.&amp;nbsp;&amp;nbsp; It is not too hard to&amp;nbsp;change the implementation to be fair, and I might take that up in a later blog (please request it if you are interested). &amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;The lock as written is also not reentrant.&amp;nbsp; It is relatively easy and efficient to add this (although it is not clear this feature is a good idea), and I show how to do that too (please request it if you are interested).&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;The code is really worth looking at carefully and I encourage you to do so.&amp;nbsp; It is small enough that you can understand the intent quickly, but there are many scenarios to think about.&amp;nbsp;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN style="FONT-SIZE: 18pt"&gt;Recap&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;What are the take-aways?&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL type=1&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo2; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;Use reader-writer locks as suggested in my first article.&amp;nbsp; If lock perf is a problem, take the implementation here as a 'drop in' replacement for the .NET System.ReaderWriterLock.&amp;nbsp; Feel free to use this implementation until Microsoft fixes the version in its library.&amp;nbsp; 
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo2; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;Spin-locks are a really valuable low lock technique.&amp;nbsp;&amp;nbsp; There were used here to make a clean, simple but efficient reader-writer lock written competely in managed code.&amp;nbsp;&amp;nbsp; This lock is &lt;EM&gt;significantly&lt;/EM&gt; simpler than most implementations I have seen, yet is clost to optimal.&amp;nbsp; The reason for this is that the use of spin locks GREATLY simplifies the design and analysis of the lock, without sacrificing performance.&amp;nbsp;&amp;nbsp; Feel free to use the Spin lock implementation show here to make other high performance concurrent constructs.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo2; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;Even something as simple as a Reader-Writer lock has subtleties about its behavior (especially when you factor in performance concerns).&amp;nbsp;&amp;nbsp; Keeping it simple really pays off here.&amp;nbsp; &lt;o:p&gt;&lt;/o:p&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=563180" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/vancem/attachment/563180.ashx" length="10633" type="text/plain" /><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/Concurrency+/default.aspx">Concurrency </category></item><item><title>How to use Visual Studio to investigate code generation questions in managed code. </title><link>http://blogs.msdn.com/vancem/archive/2006/02/20/how-to-use-visual-studio-to-investigate-code-generation-questions-in-managed-code.aspx</link><pubDate>Tue, 21 Feb 2006 01:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:535807</guid><dc:creator>vancem</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/vancem/comments/535807.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=535807</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Introduction: What does ‘foreach’ actually do?&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;It is not uncommon for a new group to want to use manage code to pepper the CLR team with performance questions. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;They want to know how expensive ‘foreach’ is, or whether certain methods get inlined or a variety of other questions about the code quality of. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Sometimes, people look at the IL in attempt to answer questions about the code quality of managed code, however this approach is misguided.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;The JIT compiler transforms the code tremendously going from IL to native, and thus for most performance questions the quality of the IL does not correlate strongly with the ultimate performance of the code. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;For codegen performance questions, what matters most is the quality of the JIT compiler. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Often internal partners will simply ask us how questions about what code gets generated for a particular construct, and every time they do this I think ‘Why should I have to do this? &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Run it under a debugger and see for yourself!’&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;This blog is the step-by-step instructions for doing just this in Visual Studio.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Conceptually, the process of determining what Native code is generated by a construct is very straightforward &lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo1; tab-stops: list .5in"&gt;Find or generate code that has the construct you wish to understand&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo1; tab-stops: list .5in"&gt;Compile the code with optimizations turned on&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l2 level1 lfo1; tab-stops: list .5in"&gt;Run it under a debugger, stepping to the code interesting code an view it in the disassembly window.&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Unfortunately, while all of these are possible to do in Visual Studio, the defaults work against you and you have to know how to change them.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;To make things concrete, I will go through the steps for an example. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;I happen to interested in looking at the the overhead of a foreach() for List&amp;lt;int&amp;gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/o:p&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;[System.Runtime.CompilerServices.&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;MethodImpl&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;(System.Runtime.CompilerServices.&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;MethodImplOptions&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.NoInlining)]&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;static void F(int arg) {}&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;static void ForEachTest(List&amp;lt;int&amp;gt; list) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;foreach (int elem in list) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;F(elem);&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Compiling the code with optimizations:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This part is almost straightforward in Visual Studio. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;You would have liked it to be the case that simply compiling the ‘Debug’ to ‘Release’ in the Solution Configuration window at the top-center of the VS IDE would be sufficient.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Unfortunately this is simply not true for C# projects (I have not checked for VB or C++ projects). &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The issue is that by default release builds do NOT build the program data base (PDB) files that hold the line number and local variable information. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;This makes it impossible for the debugger to correlate the assembly code back to line numbers. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;This makes it much more difficult to read the assembly code for large methods. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;To fix this going to the properties for the project (right click on the project in the Solution Explorer), select the ‘Build’ tab and click the ‘Advanced’ button at the bottom.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the dialog box that comes up there will be a line ‘Debug Info’.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It should be set to ‘pdb-only’.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This tells the compiler to compile with optimizations, however also create a pdb file.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;With that done, make certain your Solution Configuration&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;window says ‘Release’ and compile your solution (F6).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Running optimized managed code:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Sadly, Visual Studio makes debugging optimized code harder than you would like. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;First, by default, if you launch a managed program under Visual Studio, it will force the JIT compiler to created non-optimized native code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This improved debuggability, but makes it impossible to see that code that actually runs when the app is not run under Visual Studio. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;The other problem is that Visual Studio has a feature called ‘Just My Code’ in which the debugger will not step into code that it does not believe is being developed. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;In particular any optimized code is not considered ‘My Code’ and is skipped. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Again this makes it impossible to actually stop and see the optimized code.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;To fix both of these problems &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .75in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;1)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Go to Tools -&amp;gt; Options -&amp;gt; Debugging -&amp;gt; General &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .75in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Make certain that box labeled &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;‘Suppress JIT optimization on module load’ is UNCHECKED. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .75in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;3)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Also make certain the box labled ‘Enable Just My Code’ is also UNCHECKED. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Note that these are global settings (the affect all solutions), however, I have found I don’t miss either of these ‘features’ (Code compiled ‘Debug’ is still not optimized by the JIT so you still get good debugging there). &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Once you have disabled this ‘features’, set a breakpoint at an interesting spot (F9) and run the program (F5).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Examining the optimized code:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Once your breakpoint is hit, it is a simple matter of switching to the disassembly window (Ctrl D CtrlD, or Debug -&amp;gt; Windows -&amp;gt; Disassembly) to look at your code.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;You should not see and ‘nop’ instructions in the code. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;If you do this means you are looking at a ‘Debug’ build of your code. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;It is not a bad idea to run a simple test by creating a function that returns a constant integer and confirm that it gets inlined in the resulting assembly code. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;This confirms that all the preceding steps were successful. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;You will notice that the assembly code does not have symbolic names for the call targets. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Often this is not a hardship, because you can deduce it from the corresponding source line associated with the assembly code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If for things like ‘foreach’ or other constructs where the IL compiler is doing significant work, it is a hardship not to know what the symbolic name of the target is. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;In the case of my example above the interesting code is&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;00000077&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;mov&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ecx,dword ptr [ebp-24h] &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;F(elem);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;0000007a&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;call&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;dword ptr ds:[00913028h] &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;foreach (int elem in list) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;00000080&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;lea&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ecx,[ebp-30h] &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;00000083&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;call&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;7878BFF4 &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;00000088&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;test&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;eax,eax &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;0000008a&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;jne&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;00000077&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;So we are pretty sure that we know that &lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;dword ptr ds:[00913028h] &lt;/SPAN&gt;is really our F() method, however we don’t know what this &lt;SPAN style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;7878BFF4 &lt;/SPAN&gt;that we call a bit further down. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;You also might not know what instructions like ‘lea’ do, or how the ‘elem’ parameter is passed to our ‘F’ method. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Luckily all of these issues (and others) will be the topic of my next blog entry.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Recap:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In this blog entry I have given step-by-step instructions for using Visual Studio to look at optimized managed code. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Hopefully you will agree that is really is not that bad at all, and it now gives you the tool to answer a whole host of questions such as&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo3; tab-stops: list .75in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;1)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Is a particular method inlined or not?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo3; tab-stops: list .75in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Does the JIT perform optimization X?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Note that the example above was for X86, but the technique above works just as well for X64. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Note that the X64 JIT compiler and the X86 JIT compiler are completely different, so you if you care about performance on both platforms, you will need to repeat your experiment on both platforms. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=535807" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category><category domain="http://blogs.msdn.com/vancem/archive/tags/Tools/default.aspx">Tools</category></item><item><title>Vance Morrison's Introduction to Bloging:  Lets talk about Perf!</title><link>http://blogs.msdn.com/vancem/archive/2006/02/20/535729.aspx</link><pubDate>Tue, 21 Feb 2006 00:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:535729</guid><dc:creator>vancem</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/vancem/comments/535729.aspx</comments><wfw:commentRss>http://blogs.msdn.com/vancem/commentrss.aspx?PostID=535729</wfw:commentRss><description>&lt;P&gt;This is my first real blog entry, so I would like to introduce myself.&amp;nbsp;&amp;nbsp; My name is &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:PersonName w:st="on"&gt;Vance Morrison&lt;/st1:PersonName&gt; and I am currently a performance architect on the .NET Runtime Team.&amp;nbsp; I am one of a handful of developers who have worked on the .NET runtime from its inception.&amp;nbsp; I did most of my work in the Just in Time Compiler associated with the runtime (for example I was the primary contact for all IL opcode issues back in the time when we were actually adding opcodes).&amp;nbsp;&amp;nbsp; What is wonderful about working in the JIT compiler is that you are at what I consider the 'heart' of the runtime.&amp;nbsp;&amp;nbsp; Generally speaking, if it needs to be fast, the JIT needs to know about it.&amp;nbsp; This gave me a lot of exposure to many of the conventions that are fundamental to the runtime's operation (What is the layout of an object, or array, how do virtual method calls happen?&amp;nbsp; Where to security checks get put?&amp;nbsp; How do you report GC pointers to the GC?&amp;nbsp;&amp;nbsp; When can a GC happen?&amp;nbsp;....)&amp;nbsp; In reality the JIT has a whole is a just a performance optimization and so it is not so a big leap&amp;nbsp;for me to change from optimizing small sequences of instructions to optimizing the&amp;nbsp;runtime more&amp;nbsp;holistically &amp;nbsp; &lt;/P&gt;
&lt;P&gt;In my new role, a bit part of what I need to do is to encourage best practices.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This blog is one part of my new role.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;There has been a lot already written about .NET performance, much of which has been written by my predecessor &lt;A href="/ricom/"&gt;Rico Mariani&lt;/A&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;This is all good stuff and I have spent a bunch of time reading about it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;My focus is going to be a bit different.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I want to focus on &lt;B style="mso-bidi-font-weight: normal"&gt;TOOLS&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Part of the reason why performance is hard, is that either there are not good tools out there, or that there is not good guidance about how to use the tools well.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;For example NT has literally hundreds of performance counters.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So many it is very difficult to understand which ones are actually good for what.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;PerfMon, the tool Microsoft ships to display this information has some useful information buried in its help, but most people give up long before they find it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is also too terse to really be helpful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is really just a monitoring tool for evaluating the overall health of your system. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Once you determine your system is not healthy and have narrowed it to a particular process, you typically need other tools, and a debugger to drill further. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Thus perfmon is useful, but it is not obvious how to use it well, and is only useful for one phase of a performance investigation. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Seems like some guidance would be useful, so one of my blog entries will be on when I use perfmon, how I use it, and when I move on to other tools.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;While I like to believe that I am an authority on some things (like how the .NET framework generates code), there are many more things where I can not offer authoritative guidance (like what half the performance counters collected by windows are good for).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;In short, I too, have a lot to learn.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;What I bring to the table is a passion for performance and a desire for finding and promoting the best tools for the job. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Undoubtedly I will learn a lot for all of you along the way, and I look forward to it. &lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=535729" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/vancem/archive/tags/Perf/default.aspx">Perf</category></item></channel></rss>