views:

667

answers:

4

So for a while I've been using XslCompiledTransform because that's what Microsoft tells me I need to use as XslTransform is deprecated. Recently I had to use it with a transform that has nearly 100,000 lines (generated xsl - of course). When I used my application I was shocked to see an OOM pop up. No matter what I did - OOM is all I get... For giggles I went back to XslTransform... Same exact code changing XslCompiledTransform to XslTransform and it works fine...

Can anyone tell me how to work around the OOM - is there some 'swtich' on XslCompiledTransform? I don't know how you will be able to replicate the exact problem, but if anyone has any answers they're much appreciated.

Thanks - code below:

Works:

XslTransform myXslTransform = new XslTransform();
myXslTransform.Load(xslWith100ThousandLines);
MemoryStream m = new MemoryStream();
myXslTransform.Transform(myXPathDocument, null, m);
m.Flush();
m.Close();

Fails with OOM

XslCompiledTransform cxslt = new XslCompiledTransform();
cxslt.Load(xslWith100ThousandLines);
MemoryStream m = new MemoryStream();
cxslt.Transform(myXPathDocument, null, m);
m.Flush();
m.Close();
A: 

At first, I thought that you should file it at Microsoft Connect as a bug, but thinking about it now, it's not really a bug. With an XSL document that large, you more than likely did hit an OOM exception.

I would still post it there, just because I wouldn't expect the new XslCompiledTransform to fail when the XslTransform doesn't.

If the result document is large, maybe save the document to a temp FileStream on disk and then work from that while processing the document?

casperOne
thanks - i'm pretty sure it's a bug but i asked because often times there are settings that i can pass using some constructor or by setting some property.
dovholuk
A: 

Suprising, I was under the impression that the old XslTransform just chained to the new XslCompiledTransoform.

Did you get the OOM on the first usage? Remember, anything compiled (XslCompiledTransoform, XmlSerializer, Regex with RegexOptions.Compiled) loads assemblies into your AppDomain. Assemblies can not be removed once added to an AppDomain. You have a few options here:

  1. Load the assemblies into another AppDomain and remove that AppDomain once you are done with it. This is rather complicated and difficult. Doing it this way will allow your application to free used memory.
  2. Create a cache of XslCompiledTransforms. NEVER create the transform again. This way will allow your application to curb growth of memory usage. You might want to (hash+base64)/checksum the XSL beforehand and use that string as a key in the dictionary.

If you are generating that XSLT file at design time, it may be worth your while retrieving the assembly created by it and packaging it with your application instead of the XSLT. If it is at runtime, you will have to go with option (1) above.

Jonathan C Dickinson
I wish there were better mechanisms of 'commenting'... comments don't have the visibility of answers and hence are 'lacking'... (to me anyway)i was under the same impression as you - and i was surprised to see this behavior.the app is a console app so it's on first usage. (more in next comment)
dovholuk
the full code is exactly as I stated above...
dovholuk
damn. looks like you are really stuck then. can you put xslt on a ftp site somewhere?
Jonathan C Dickinson
A: 
dovholuk
+1  A: 

ok, so now i think, maybe this is more 'microsoft being microsoft'... on a hunch i changed the target platform back to "Any CPU", closed ALL my visual studio instances open and reopened my project... i then cleaned, recompiled, and reran and i am again getting the OOM...

i then set the target platform back to x86 and low and behold no more OOM! i've had a lot of x64 related issues like this and in the future i will be sure to include them in any postings... more often than not it's due to x64...

odd... but problem 'solved'... :S

dovholuk
huh... that is really odd!
Jonathan C Dickinson
by the way, you might still consider extracting the generated assembly as a dll. This would allow you to limit the 32bit fingerprint (instead of having to compile your entire assembly 32bit).
Jonathan C Dickinson