<?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>Marcelo's WebLog : Performance</title><link>http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx</link><description>Tags: Performance</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>MSXML XHTML DTDs - making the web better</title><link>http://blogs.msdn.com/marcelolr/archive/2009/11/30/msxml-xhtml-dtds-making-the-web-better.aspx</link><pubDate>Mon, 30 Nov 2009 22:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9928868</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9928868.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9928868</wfw:commentRss><description>&lt;P&gt;The fix to requests for XHTML DTD files from the W3C Web server has been recently released. Windows Update should offer the fix automatically, but you can download and install the fix manually from the following links for various MSXML versions:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://support.microsoft.com/?kbid=973688"&gt;http://support.microsoft.com/?kbid=973688&lt;/A&gt; [MSXML4 SP2... if you haven't tried SP3 yet see below]&lt;BR&gt;&lt;A href="http://support.microsoft.com/?kbid=973685"&gt;http://support.microsoft.com/?kbid=973685&lt;/A&gt; [&lt;A href="http://blogs.msdn.com/xmlteam/archive/2009/03/06/msxml4-sp3-is-available-now.aspx" mce_href="http://blogs.msdn.com/xmlteam/archive/2009/03/06/msxml4-sp3-is-available-now.aspx"&gt;MSXML4 SP3&lt;/A&gt;]&lt;BR&gt;&lt;A href="http://support.microsoft.com/?kbid=973686"&gt;http://support.microsoft.com/?kbid=973686&lt;/A&gt; [MSXML6 Out-Of-Band, for XP SP2 and Win2K3]&lt;BR&gt;&lt;A href="http://support.microsoft.com/?kbid=973687"&gt;http://support.microsoft.com/?kbid=973687&lt;/A&gt; [MSXML3 and MSXML6 for all OSes where these components are in-band]&lt;/P&gt;
&lt;P&gt;What exactly is this about? Well, there are a number of cases where this can happen, but one common scenario that we've seen people run into when writing AJAX web pages is to request a page of information from the server, load it into an XML document and extract some information or merge it into the existing page.&lt;/P&gt;
&lt;P&gt;The problem with this approach is that when you load the document into an MSXML document "by hand" (ie, not through &lt;A href="http://msdn.microsoft.com/en-us/library/ms534370.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms534370.aspx"&gt;responseXML&lt;/A&gt; on the XHR object), DTD processing is enabled, and the DOCTYPE declaration directs MSXML to go look up the XHTML DTD so you can use entities like &amp;amp;nbsp;.&lt;/P&gt;
&lt;P&gt;Multiply this by each web browser accessing a popular site, and you can imagine why no-one is happy with this situation: web sites break when the resource is not available, the W3C servers get overloaded, and users of web sites lose functionality with odd scripting errors.&lt;/P&gt;
&lt;P&gt;The fix caches the XHTML DTDs in MSXML - these resources haven't changed for years and will likely end up in different URLs if something new comes along. So now clients save at least one round-trip (possibly more) and always get the DTD support they need.&lt;/P&gt;
&lt;P&gt;Try running this bit of script in a .js file to see the awesomeness in action.&lt;/P&gt;
&lt;P style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;function pullXHtml() {&lt;BR&gt;&amp;nbsp; var xml = new ActiveXObject("Msxml2.DOMDocument.3.0");&lt;BR&gt;&amp;nbsp; xml.async = false;&lt;BR&gt;&amp;nbsp; xml.loadXML(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"&amp;gt;" +&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;simple document&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;" +&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;body&amp;gt;&amp;lt;p&amp;gt;a simple&amp;amp;nbsp;paragraph&amp;lt;/p&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;");&lt;BR&gt;&amp;nbsp; if (xml.parseError.errorCode != 0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var myErr = xml.parseError;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WScript.Echo("You have error " + myErr.reason);&lt;BR&gt;&amp;nbsp; } else {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WScript.echo("Yay!");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WScript.echo(xml.xml);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;pullXHtml();&lt;/P&gt;
&lt;P&gt;If you don't have the update, you might get an error such as the following.&lt;/P&gt;
&lt;P style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;You have error The server did not understand the request, or the request was invalid.&lt;BR&gt;Error processing resource 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'.&lt;/P&gt;
&lt;P&gt;If you do have the update, you'll see the parsed XML. Run this with &lt;A href="http://www.fiddler2.com/fiddler2/" mce_href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/A&gt; open and you'll&amp;nbsp;"see" the absence of network activity.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9928868" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>Performance Tools</title><link>http://blogs.msdn.com/marcelolr/archive/2009/06/12/performance-tools.aspx</link><pubDate>Sat, 13 Jun 2009 00:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9729807</guid><dc:creator>marcelolr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9729807.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9729807</wfw:commentRss><description>&lt;P&gt;I've written about performance tools in the past - it's a topic that interests me quite a bit, because I believe that perceived performance is a very fundamental part of the user experience and can wow you or frustrate you immensely. And I believe "real performance" (so to speak) is very important of course, especially when you don't have a person sitting in front of the computer, but I think every developer will appreciate the difference that a 2' checkin script has vs. a 20' checkin script or a 60' script. 'Nuff said.&lt;/P&gt;
&lt;P&gt;In any case, this post about &lt;A href="http://blogs.msdn.com/profiler/archive/2009/06/10/write-faster-code-with-vs-2010-profiler.aspx" mce_href="http://blogs.msdn.com/profiler/archive/2009/06/10/write-faster-code-with-vs-2010-profiler.aspx"&gt;Visual Studio 2010 profiler tools&lt;/A&gt; shows some fabulously productive stuff. And all with Visual Studio usability, rather than what it feels like to use some of the more arcane tools (that are admittedly very well suited to automated scenarios, we'll always grant them that).&lt;/P&gt;
&lt;P&gt;Anyway, read up and enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9729807" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category></item><item><title>DTD resolution and network behavior</title><link>http://blogs.msdn.com/marcelolr/archive/2009/04/20/dtd-resolution-and-network-behavior.aspx</link><pubDate>Tue, 21 Apr 2009 00:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9555509</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9555509.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9555509</wfw:commentRss><description>&lt;P&gt;Following up from my &lt;A href="http://blogs.msdn.com/marcelolr/archive/2009/04/17/faster-xml-don-t-resolve-dtds-if-you-don-t-need-to.aspx" mce_href="http://blogs.msdn.com/marcelolr/archive/2009/04/17/faster-xml-don-t-resolve-dtds-if-you-don-t-need-to.aspx"&gt;last post&lt;/A&gt;, &lt;A href="http://blogs.msdn.com/user/Profile.aspx?UserID=106840" mce_href="http://blogs.msdn.com/user/Profile.aspx?UserID=106840"&gt;danieldsmith&lt;/A&gt; asked about a couple of additional details. I &lt;EM&gt;think&lt;/EM&gt; I responded in the comments, but because (a) it's generally useful, and (b) I had some problems with my network connection (because I monkeying around with it), the reply may have been lost. So here we go again.&lt;/P&gt;
&lt;P&gt;First, is caching implemented for the resolved DTDs? No, the default resolver doesn't do any caching&amp;nbsp;- files will always be requested. So if you're loading documents with DTDs in a tight loop, you might get a pretty significant perf improvement here.&lt;/P&gt;
&lt;P&gt;Second, what happens if there is no network connectivity? Well, the framework can't do validation without the DTD, and even if it could it would be unable to expand entities, so as you might guess, the problem isn't silently ignored - you'll get an exception instead.&lt;/P&gt;
&lt;P&gt;Trying this on my machine at home, I got two slightly different exception - your mileage may vary. The first time I had Fiddler running, and I got a &lt;A href="http://msdn.microsoft.com/en-us/library/system.net.webexception.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.net.webexception.aspx"&gt;System.Net.WebException&lt;/A&gt; with a Message value "The remote server returned an error: (502) Bad Gateway.", and a Status value of &lt;A href="http://msdn.microsoft.com/en-us/library/system.net.webexceptionstatus.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.net.webexceptionstatus.aspx"&gt;ProtocolError&lt;/A&gt;. There was a Response assigned to it, which had a message of its own, "Fiddler - DNS Lookup Failed".&lt;/P&gt;
&lt;P&gt;Then I shut down Fiddler and got another WebException, although this time the message was "The remote name could not be resolved: 'www.w3.org'", and the Response of the exception was null.&lt;/P&gt;
&lt;P&gt;So now you know. Keep an eye on your network activity, and turn off features that you don't use to get perf / stability improvements without having to go and make changes to your application.&lt;/P&gt;
&lt;P&gt;As a side note, I like to run &lt;A href="http://www.fiddler2.com/Fiddler2/" mce_href="http://www.fiddler2.com/Fiddler2/"&gt;Fiddler&lt;/A&gt; every now and then, just to see what kind of web traffic my machine is generating - it's awfully interesting to see the kinds of things that are going on sometimes.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9555509" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>Faster XML - don't resolve DTDs if you don't need to</title><link>http://blogs.msdn.com/marcelolr/archive/2009/04/17/faster-xml-don-t-resolve-dtds-if-you-don-t-need-to.aspx</link><pubDate>Sat, 18 Apr 2009 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9554665</guid><dc:creator>marcelolr</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9554665.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9554665</wfw:commentRss><description>&lt;P&gt;When loading an XML document through &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.load.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.load.aspx"&gt;XmlDocument.Load&lt;/A&gt; or &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.load.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.load.aspx"&gt;XDocument.Load&lt;/A&gt;, the default behavior when finding a DTD reference is to go resolve the URL, which typically means one or more web requests. Often, however, the DTD is there more as a marker of what the document contains than anything else, and you might not want to reference entities or do validation.&lt;/P&gt;
&lt;P&gt;For example, let's say I have the following code. This will load an XML document from a string, then write it out to the console.&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;const&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; xmlText = &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&lt;BR&gt;@"&amp;lt;!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'&amp;gt;&lt;BR&gt;&amp;lt;html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'&amp;gt;&lt;BR&gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Hello&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;BR&gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello from XHTML&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&lt;BR&gt;&amp;lt;/html&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&lt;BR&gt;XmlDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; doc = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;doc.LoadXml(xmlText);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(doc.InnerXml);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.ReadKey();&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;The problem here is that there is no reason for us to access the DTD for this particular application, and yet the following requests will go out.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&lt;/A&gt;&lt;BR&gt;&lt;A href="http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent&lt;/A&gt;&lt;BR&gt;&lt;A href="http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent&lt;/A&gt;&lt;BR&gt;&lt;A href="http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The first solution, available on Silverlight, is to use the &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.resolvers.xmlpreloadedresolver(VS.95).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.resolvers.xmlpreloadedresolver(VS.95).aspx"&gt;XmlPreloadedResolver&lt;/A&gt;. By default it will contain DTDs for XHTML and RSS, but you can add your own. In this case, you get the same level of functionality as if the real resources had been requests. For example, you can use entity references such as &lt;EM&gt;&amp;amp;nbsp;&lt;/EM&gt; to mean "non-breaking white space". If you assign an instance as your &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.xmlresolver.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.xmlresolver.aspx"&gt;XmlResolver&lt;/A&gt;, you're good to go.&lt;/P&gt;
&lt;P&gt;A second solution, which is also available on the full .NET Framework, is to simply set the XmlResolver property to &lt;EM&gt;null&lt;/EM&gt;. In this case, no requests will be made at all, but you won't be able to use entity references nor have the document validated.&lt;/P&gt;
&lt;P&gt;Note that this isn't just available on XmlDocument, but also through &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx"&gt;XmlReaderSettings&lt;/A&gt;, anytime you're creating an XmlReader (which can of course be used with both XmlDocument and&amp;nbsp;XDocument, along with many other parts of the framework).&lt;/P&gt;
&lt;P&gt;In the next release of the .NET Framework, there will be a few other ways in which you may save the resource requests, but these options are available to you today.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9554665" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>Velocity at DevConnections</title><link>http://blogs.msdn.com/marcelolr/archive/2009/03/20/velocity-at-devconnections.aspx</link><pubDate>Sat, 21 Mar 2009 00:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9491839</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9491839.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9491839</wfw:commentRss><description>&lt;P&gt;Next Monday I'll be at &lt;A href="http://www.devconnections.com/" mce_href="http://www.devconnections.com/"&gt;DevConnections&lt;/A&gt; in Orlando, talking about &lt;A href="http://msdn.microsoft.com/en-us/data/cc655792.aspx" mce_href="http://msdn.microsoft.com/en-us/data/cc655792.aspx"&gt;Velocity&lt;/A&gt; (Microsoft Project Code Named "Velocity", if you like formality).&lt;/P&gt;
&lt;P&gt;It's going to be a bit of a challenge to sum up all that awesomeness into a single session, but I promise I'll do my best, and I'll be around for the rest of the event in case anyone wants to get in touch. Contact through email and blog will be slow, but should get back in rhythm after the event.&lt;/P&gt;
&lt;P&gt;In case you find the online list a tad long to search through, the session is titled an unsurprising &lt;EM&gt;MDA02: Microsoft Project Codenamed Velocity: A Distributed In-memory Cache&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;See you in Orlando!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9491839" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Velocity/default.aspx">Velocity</category></item><item><title>XmlSchema and XmlSchemaSet thread safety</title><link>http://blogs.msdn.com/marcelolr/archive/2009/03/16/xmlschema-and-xmlschemaset-thread-safety.aspx</link><pubDate>Tue, 17 Mar 2009 00:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9472742</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9472742.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9472742</wfw:commentRss><description>&lt;P&gt;Here's a good word of warning: even if an object "feels" read-only because you're not calling code to modify it, if it's not documented as safe for use from multiple threads, then you shouldn't risk it.&lt;/P&gt;
&lt;P&gt;In particular, I'd like to talk about &lt;A class="" href="http://msdn.microsoft.com/en-us/library/system.xml.schema.xmlschema.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.schema.xmlschema.aspx"&gt;XmlSchema&lt;/A&gt; and &lt;A class="" href="http://msdn.microsoft.com/en-us/library/system.xml.schema.xmlschemaset.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.schema.xmlschemaset.aspx"&gt;XmlSchemaSet&lt;/A&gt; today. Building these has a cost associated, and so it's nice to be able to build them once and then reuse them. But you have to be very careful in doing this. The docs say that all instance methods are not safe for multiple thread usage, but you don't really use them directly during validation, so it's hard to tell from the outside what's safe and what's not.&lt;/P&gt;
&lt;P&gt;In a nutshell, the only thing you can do that is safe for concurrent usage is to use a validating reader. Here's the sample code to try this out (for some reason, this "breaks" more on 64-bit machines, but it's unsafe on all architectures).&lt;/P&gt;
&lt;P&gt;First, a little helper to create an XmlSchema.&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchema&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; CreateSchema()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; schemaText = &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;@"&amp;lt;?xml version='1.0'?&amp;gt;&lt;BR&gt;&amp;lt;xs:schema id='play' targetNamespace='http://tempuri.org/play.xsd'&lt;BR&gt;&amp;nbsp;elementFormDefault='qualified' xmlns='http://tempuri.org/play.xsd'&lt;BR&gt;&amp;nbsp;xmlns:xs='http://www.w3.org/2001/XMLSchema'&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;lt;xs:element name='myShoeSize'&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;xs:complexType&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;xs:simpleContent&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:extension base='xs:decimal'&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:attribute name='sizing' type='xs:string' /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:extension&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:simpleContent&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;/xs:complexType&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;/xs:element&amp;gt;&lt;BR&gt;&amp;lt;/xs:schema&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;StringReader&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; reader = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;StringReader&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;(schemaText))&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchema&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Read(reader, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;P&gt;Next, a simple XmlSchemaSet.&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchemaSet&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; CreateSchemaSet(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchema&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; schema)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchemaSet&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; set = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchemaSet&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&amp;nbsp; set.Add(schema);&lt;BR&gt;&amp;nbsp; set.Compile();&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; set;&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;P&gt;Finally, some validation:&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; ValidateDocument(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchemaSet&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; set)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; doc = &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;@"&amp;lt;myShoeSize xmlns='http://tempuri.org/play.xsd' sizing='123' /&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlReaderSettings&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; settings = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlReaderSettings&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&amp;nbsp; settings.Schemas = set;&lt;BR&gt;&amp;nbsp; settings.ValidationEventHandler += &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;ValidationEventHandler&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;(settings_ValidationEventHandler);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;StringReader&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; reader = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;StringReader&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;(doc))&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlReader&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; x = &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlReader&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Create(reader, settings))&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;while&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (x.Read()) { }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&lt;BR&gt;private&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#000000&gt; failCount;&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;void&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; settings_ValidationEventHandler(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;ValidationEventArgs&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; System.Threading.&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Interlocked&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Increment(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;ref&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; failCount);&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/FONT&gt;Now, armed with these, I will show you some code that &lt;EM&gt;is&lt;/EM&gt; thread-safe, but that a single line reorder would cause to break.&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchema&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; schema = CreateSchema();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Thread&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;[] threads = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Thread&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;[10];&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlSchemaSet&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; set = CreateSchemaSet(schema);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; i = 0; i &amp;lt; threads.Length; i++)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; threads[i] = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Thread&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;((x) =&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; j = 0; j &amp;lt; 1000; j++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// If the CreateSchemaSet were here&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// instead of outside this would break!&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;//&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// Don't add the schema to the &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// XmlSchemaSet from multiple threads!&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// XmlSchemaSet set = CreateSchemaSet(schema);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;//&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;ValidateDocument(set);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Array&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.ForEach(threads, (t) =&amp;gt; t.Start());&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Array&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.ForEach(threads, (t) =&amp;gt; t.Join());&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Text = &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"Failure count: "&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; + failCount;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;The part before the thread creation is all thread-safe; the stuff inside the callback&amp;nbsp;is happening on multiple threads at the same time. You can only use the set for validation here!&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9472742" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>Fast way to convert XmlDocument into XDocument</title><link>http://blogs.msdn.com/marcelolr/archive/2009/03/13/fast-way-to-convert-xmldocument-into-xdocument.aspx</link><pubDate>Sat, 14 Mar 2009 00:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9471290</guid><dc:creator>marcelolr</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9471290.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9471290</wfw:commentRss><description>&lt;P&gt;This question came up in &lt;A class="" href="http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/threads/" mce_href="http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/threads/"&gt;the forums&lt;/A&gt; a little while ago, and I thought it might be interesting to do some comparisons.&lt;/P&gt;
&lt;P&gt;I first came up with a few ways of turning an XmlDocument into an XDocument.&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; DocumentToXDocument(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; doc)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Parse(doc.OuterXml);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; DocumentToXDocumentNavigator(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; doc)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Load(doc.CreateNavigator().ReadSubtree());&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; DocumentToXDocumentReader(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; doc)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Load(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlNodeReader&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;(doc));&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;P&gt;Next I whipped up a function to time these with something quick and dirty. I make sure the past activity doesn't both much in terms of leaving garbage, and I warm up the action a bit (I also warm up the Stopwatch methods, just in case).&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;long&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; Time(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; count, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Action&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; action)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;GC&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Collect();&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; i = 0; i &amp;lt; 3; i++)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; action();&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Stopwatch&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; watch = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Stopwatch&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&amp;nbsp; watch.Start();&lt;BR&gt;&amp;nbsp; watch.Stop();&lt;BR&gt;&amp;nbsp; watch.Reset();&lt;BR&gt;&amp;nbsp; watch.Start();&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; i = 0; i &amp;lt; count; i++)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; action();&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;long&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; result = watch.ElapsedMilliseconds;&lt;BR&gt;&amp;nbsp; watch.Stop();&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; result;&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;P&gt;And finally, all together:&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;
&lt;P&gt;StringBuilder&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; sb = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;StringBuilder&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;sb.Append(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"&amp;lt;parent&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; i = 0; i &amp;lt; 1000; i++)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; sb.Append(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;" &amp;lt;child&amp;gt;text&amp;lt;/child&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;}&lt;BR&gt;sb.Append(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"&amp;lt;/parent&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; text = sb.ToString();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; doc = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;XmlDocument&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;doc.LoadXml(text);&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;long&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; docToXDoc = Time(1000, () =&amp;gt; DocumentToXDocument(doc));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;long&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; docToXDocNavigator = Time(1000, () =&amp;gt; DocumentToXDocumentNavigator(doc));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;long&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; docToXDocReader = Time(1000, () =&amp;gt; DocumentToXDocumentReader(doc));&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Note that the actual numbers don't matter much, as this is my laptop running a bunch of things in the background, in the debugger and whatnot, but the relative values are interesting to see.&lt;/P&gt;
&lt;P&gt;These are the values I got (they vary a bit each run, but not by much).&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Using OuterXml: 1973 ms.&lt;/LI&gt;
&lt;LI&gt;Using a navigator over the document: 1254 ms.&lt;/LI&gt;
&lt;LI&gt;Using a reader over the document: 1154 ms.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Not surprisingly, avoiding the creation of a big string just to re-parse it is a big win - save the planet, use less CPU power!&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9471290" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>XmlDocument.PreserveWhitespace and memory usage</title><link>http://blogs.msdn.com/marcelolr/archive/2009/03/06/xmldocument-preservewhitespace-and-memory-usage.aspx</link><pubDate>Sat, 07 Mar 2009 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9460677</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9460677.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9460677</wfw:commentRss><description>&lt;P&gt;The &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.preservewhitespace.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.preservewhitespace.aspx"&gt;PreserveWhitespace&lt;/A&gt; property is sometimes misunderstood. As &lt;A href="http://msdn.microsoft.com/en-us/library/ab0dyby0.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ab0dyby0.aspx"&gt;this MSDN page&lt;/A&gt; describes, this affects non-significant whitespace nodes. Significant whitespace is always preserved.&lt;/P&gt;
&lt;P&gt;So what is significant whitespace? The &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.xmlsignificantwhitespace.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.xmlsignificantwhitespace.aspx"&gt;XmlSignificantWhitespace&lt;/A&gt; explains: it's the whitespace under the scope of an &lt;EM&gt;xml:space='preserve'&lt;/EM&gt;, or the whitespace between elements in a mixed content node (with both elements and text).&lt;/P&gt;
&lt;P&gt;For many documents, non-significant whitespace is, well, not significant. It's just there so elements align and are more readable to humans, but processors aren't expected to do anything with it.&lt;/P&gt;
&lt;P&gt;So if your program doesn't need it, there's no need for you to pay the price of creating objects to represent them and&amp;nbsp;keep them in your document tree. If you do "typical" indentation, where every element is on a different line and you indent as elements get deeper, then you may actually save yourself some memory by getting rid of the whitespace. Thankfully, PreserveWhitespace defaults to &lt;EM&gt;false&lt;/EM&gt; for XmlDocument, but I've seen cases where folks turn it to true because they aren't quite sure of what it does and it feels safer to not throw something away.&lt;/P&gt;
&lt;P&gt;Here's a little snippet that shows the impact (your mileage may vary of course, depending on CPU architecture, version, compiler settings, etc).&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;bool&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;[] preserves = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;[] { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; };&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;foreach&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; preserve &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;in&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; preserves)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; GC&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Collect();&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;&amp;nbsp; // Build a document.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; StringBuilder&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; s = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;StringBuilder&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;();&lt;BR&gt;&amp;nbsp; s.AppendLine(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"&amp;lt;root&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp; for&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; i = 0; i &amp;lt; 1000; i++)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; s.AppendLine(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;" &amp;lt;element with='attributes' /&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; s.AppendLine(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"&amp;lt;/root&amp;gt;"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&lt;BR&gt;&amp;nbsp; string&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; text = s.ToString();&lt;BR&gt;&amp;nbsp; XmlDocument doc = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; XmlDocument();&lt;BR&gt;&amp;nbsp; doc.PreserveWhitespace = preserve;&lt;BR&gt;&amp;nbsp; doc.LoadXml(text);&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "PreserveWhitespace: "&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; + preserve);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Memory used before collection: {0}"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.GetTotalMemory(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; GC&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.Collect();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine(&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Memory used after full collection: {0}"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.GetTotalMemory(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;));&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; Console&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.WriteLine();&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp; GC&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.KeepAlive(doc);&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;P&gt;And this is the output I get on my machine.&lt;/P&gt;
&lt;DIV style="FONT-FAMILY: Consolas, Lucida Console, Courier New"&gt;
&lt;P&gt;PreserveWhitespace: True&lt;BR&gt;Memory used before collection:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 456616&lt;BR&gt;Memory used after full collection: 280208&lt;BR&gt;&lt;BR&gt;PreserveWhitespace: False&lt;BR&gt;Memory used before collection:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 405480&lt;BR&gt;Memory used after full collection: 232072&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;So (280208 - 232072) / 280208 ~= 17%, which isn't too bad for a line of code you don't have to write (because it's the default after all).&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9460677" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>Cloning an XmlDocument doesn't make the copy thread safe</title><link>http://blogs.msdn.com/marcelolr/archive/2009/03/04/cloning-an-xmldocument-doesn-t-make-the-copy-thread-safe.aspx</link><pubDate>Thu, 05 Mar 2009 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9450221</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9450221.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9450221</wfw:commentRss><description>&lt;P&gt;This could be a gotcha, but cloning an XmlDocument doesn't quite make a completely independent copy.&lt;/P&gt;
&lt;P&gt;The &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.clonenode.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.clonenode.aspx"&gt;CloneNode&lt;/A&gt; method is intended in general to be a way of creating copies of XML nodes under the same XmlDocument scope / owner XmlDocument. Cloning the XmlDocument does create a copy, but it shares the same scope, which has pretty much shrank to the shared NameTable / implementation at that point.&lt;/P&gt;
&lt;P&gt;So you can write a thread-safe implementation of NameTable and use that in the constructor of the original document, or you create a new document and then ImportNode, which will create a distinct node under the new document.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9450221" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>StackOverflowException with XslCompiledTransform</title><link>http://blogs.msdn.com/marcelolr/archive/2009/02/19/stackoverflowexception-with-xslcompiledtransform.aspx</link><pubDate>Fri, 20 Feb 2009 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9433324</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9433324.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9433324</wfw:commentRss><description>&lt;P&gt;Pawel recently looked into a customer report about &lt;A class="" href="http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/thread/6edac9a7-0cf0-45a6-b196-c4308b54b937/" mce_href="http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/thread/6edac9a7-0cf0-45a6-b196-c4308b54b937/"&gt;XslCompiledTransform failing with a StackOverflowException&lt;/A&gt; after an upgrade to .NET Framework 3.5 SP1. Same stylesheet, same everything, but now the exception was showing up when it wasn't before.&lt;/P&gt;
&lt;P&gt;There were a number of interesting gotchas associated with this.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The default stack size is smaller when running under IIS, which can lead to spending time figuring out whether you actually have the correct repro or not if you're running in a standalone app.&lt;/LI&gt;
&lt;LI&gt;It turns out that the stylesheet had always been close to the stack limit, but a change in the JIT to improve speed increased stack usage some, and pushed the stack over the limit.&lt;/LI&gt;
&lt;LI&gt;There are ways to rewrite the stylesheet to produce the same results but not consume as much stack internally (yay! - no configuration changes needed)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;An interesting point that shouldn't be overlooked is that if you're not going to be changing the XSL at run-time, the &lt;A class="" href="http://msdn.microsoft.com/en-us/library/bb399405.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb399405.aspx"&gt;XSLT compiler&lt;/A&gt; is a &lt;A class="" href="http://msdn.microsoft.com/en-us/library/bb399419.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb399419.aspx"&gt;great choice&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;For the real-deal details, I'll refer you to the MSDN Forum thread &lt;A class="" href="http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/thread/6edac9a7-0cf0-45a6-b196-c4308b54b937/" mce_href="http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/thread/6edac9a7-0cf0-45a6-b196-c4308b54b937/"&gt;again&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9433324" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>The one where lame excuses are given</title><link>http://blogs.msdn.com/marcelolr/archive/2009/02/06/the-one-where-lame-excuses-are-given.aspx</link><pubDate>Sat, 07 Feb 2009 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9402786</guid><dc:creator>marcelolr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9402786.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9402786</wfw:commentRss><description>&lt;P&gt;Yes, yes, yes - I've been busy. I'm sure you saw that one coming. Also I've been working on things which are top-secret, yadda-yadda.&lt;/P&gt;
&lt;P&gt;To reduce my lameness level, however, I'm back to writing for 2009 and I'll begin by linking to a very nice article which has certainly aged well: &lt;A href="http://msdn.microsoft.com/en-us/library/aa302292.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa302292.aspx"&gt;XML Reader with Bookmarks&lt;/A&gt;. This is great for those cases in which you &lt;EM&gt;mostly&lt;/EM&gt; need forward-only processing of XML, but for a very few select cases you might need to rewind (also known as "peek ahead some amount"). A great example of "pay for play" - much better than having to choose between forward-only or all-in-memory.&lt;/P&gt;
&lt;P&gt;And one of the benefits of having a long-running blog is that I can now look back and think - what I was I writing about in early 2005? &lt;A href="http://blogs.msdn.com/marcelolr/archive/2005/02/03/366770.aspx" mce_href="http://blogs.msdn.com/marcelolr/archive/2005/02/03/366770.aspx"&gt;Being effective with Outlook&lt;/A&gt;, it seems. I was a lot less prolific back then as well - clearly Avalon (WPF these days) took a lot of my time, that with the programmatic stuff, the new XAML markup and whatnot...&lt;/P&gt;
&lt;P&gt;Any implied references to the continued relevance of XML over time and across technologies is, of course, mostly unintentional.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9402786" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/XML/default.aspx">XML</category></item><item><title>Depth vs. width in ADO.NET Data Services $expand</title><link>http://blogs.msdn.com/marcelolr/archive/2008/12/01/depth-vs-width-in-ado-net-data-services-expand.aspx</link><pubDate>Tue, 02 Dec 2008 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9161268</guid><dc:creator>marcelolr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9161268.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9161268</wfw:commentRss><description>&lt;P&gt;The $expand option in the query filter is used to request entities associated with the last segment of a request. This is often used to ensure that entities can be materialized with their relationships wired together and to reduce the number of roundtrips to the server.&lt;/P&gt;
&lt;P&gt;For example, if &lt;CODE&gt;http://www.example.com/service.svc/Customers&lt;/CODE&gt; returns all customers, then &lt;CODE&gt;http://www.example.com/service.svc/Customers?$expand=Orders&lt;/CODE&gt; could be used to return all customers with all their Orders, assuming customers have an &lt;EM&gt;Orders&lt;/EM&gt; collection.&lt;/P&gt;
&lt;P&gt;You can use request multiple references and collections to be exapnded. One gotcha about the $expand syntax is that there is a different syntax for "drilling" through references: the forward slash is used to indicate drilling in, while a comma is used to separate the parallel expansion paths.&lt;/P&gt;
&lt;P&gt;Here are some examples that will hopefully clarify this (omitting the path to the service).&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;/Customers?$expand=Orders&lt;/CODE&gt;. Returns customers and the orders of the customers.&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;/Customers?$expand=Orders,Preferences&lt;/CODE&gt;. Returns customers and the preferences of the customers.&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;/Customers?$expand=Orders,Orders/OrderDetails,Preferences&lt;/CODE&gt;. Returns customers, the orders of the customers, the order details of the orders of the customers, and the preferences of the customers.&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;/Customers?$expand=Orders/OrderDetails,Preferences&lt;/CODE&gt;. Same as the last one - when you go deep, all the parents are implied, so &lt;EM&gt;Orders/OrderDetails&lt;/EM&gt;Orders&lt;/EM&gt;.&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;/Customers?$expand=Orders/OrderDetails,Orders/ShippingInfo&lt;/CODE&gt;. Returns customers, the orders of the customers, the order details of the orders of the customers, and the shipping informatio of the orders of the customers. Note that the ',' is used to separate paths starting from the last segment (&lt;EM&gt;Customers&lt;/EM&gt;), so if you want to expand properties in parallel from a deeper entity, you need to specify the path again, as in this example.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Hope this was helpful - please post comments if you have further questions!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9161268" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Entities/default.aspx">Entities</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>Limiting how many entities are returned from an ADO.NET Data Service</title><link>http://blogs.msdn.com/marcelolr/archive/2008/11/19/limiting-how-many-entities-are-returned-from-an-ado-net-data-service.aspx</link><pubDate>Thu, 20 Nov 2008 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9113782</guid><dc:creator>marcelolr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9113782.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9113782</wfw:commentRss><description>&lt;P&gt;If you want to limit the number of entities returned from a service, you have a few alternatives...&lt;/P&gt;
&lt;P&gt;If you're writing code for the&amp;nbsp;client, the easiest way is to just use the '$top' clause to limit how many entities will be returned. Note that '$top' doesn't account for entities you expand using '$expand', so be careful with what you expand if you're using it.&lt;/P&gt;
&lt;P&gt;That pretty much covers it for the options on the client - the server however is a more interesting thing.&lt;/P&gt;
&lt;P&gt;First, you have the configuration options. &lt;A class="" href="http://msdn.microsoft.com/en-us/library/system.data.services.idataserviceconfiguration.maxresultspercollection.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.idataserviceconfiguration.maxresultspercollection.aspx"&gt;MaxResultsPerCollection&lt;/A&gt; allows you to limit not only the number of entities returned at the top level of a request, but also at each collection within, so clients can't use '$expand' to overwhelm the server. Because a batch request can have multiple queries, you can combine that with &lt;A class="" href="http://msdn.microsoft.com/en-us/library/system.data.services.idataserviceconfiguration.maxbatchcount.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.idataserviceconfiguration.maxbatchcount.aspx"&gt;MaxBatchCount&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;The problem with using the configuration on the server is that it's meant more as a security feature than as a general paging mechanism, and as such the responses returned will (a) likely cause the client to error, because the response ends mid-stream, and (b) the client will have no good way to "continue" asking for data from where the last request left off.&lt;/P&gt;
&lt;P&gt;A better approach might be to ask clients to be explicit about how many entities they're willing to handle at once using the '$top' option, and overriding the &lt;A class="" href="http://msdn.microsoft.com/en-us/library/cc646889.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc646889.aspx"&gt;OnStartProcessingRequest&lt;/A&gt; method on the data service to check that the URL has indeed specified the '$top' option. Of course, you still want to set the configuration to safeguard your server!&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9113782" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>Windows Performance Analysis Developer Center</title><link>http://blogs.msdn.com/marcelolr/archive/2008/11/04/windows-performance-analysis-developer-center.aspx</link><pubDate>Wed, 05 Nov 2008 01:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9020704</guid><dc:creator>marcelolr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9020704.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9020704</wfw:commentRss><description>&lt;P&gt;Congratulations to the folks working on the Windows Performance Toolkit and friends!&lt;/P&gt;
&lt;P&gt;There's now a developer center you can use as a portal with pointers to resources, downloads, forums, FAQs, and guides to learning about the tools and getting started.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/en-us/performance/default.aspx"&gt;http://msdn.microsoft.com/en-us/performance/default.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;As you can see from the &lt;A class="" href="http://msdn.microsoft.com/en-us/library/cc305190.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc305190.aspx"&gt;Powerful Features&lt;/A&gt; topic, some of the fun things you can do include viewing machine-wide activity, cross-referencing I/O with processes and stacks, and activity across different processes. Awesome tool when you need to go beyond a single user process and start looking at system-wide activity to investigate performance.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9020704" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category></item><item><title>Profiling WPF Tools - not just for WPF</title><link>http://blogs.msdn.com/marcelolr/archive/2008/10/31/profiling-wpf-tools-not-just-for-wpf.aspx</link><pubDate>Sat, 01 Nov 2008 00:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9019379</guid><dc:creator>marcelolr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/marcelolr/comments/9019379.aspx</comments><wfw:commentRss>http://blogs.msdn.com/marcelolr/commentrss.aspx?PostID=9019379</wfw:commentRss><description>&lt;P&gt;Windows Presentation Foundation (WPF) has recently had a refresh to its performance tools. You can read more about it on the &lt;A class="" href="http://windowsclient.net/wpf/perf/wpf-perf-tool.aspx" mce_href="http://windowsclient.net/wpf/perf/wpf-perf-tool.aspx"&gt;What's New for Performance Profiling Tools for WPF&lt;/A&gt; post.&lt;/P&gt;
&lt;P&gt;The suite of tools includes a bunch of very interesting tools, one of which is a string allocator profiler. The good news is - you don't need to be working on a WPF application to be able to use it! You can just point it to any app you have, and you'll get a tree view of function calls and the count and size of strings allocated - very handy stuff to find where those allocation are coming from.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9019379" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/marcelolr/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/marcelolr/archive/tags/Performance/default.aspx">Performance</category></item></channel></rss>