views:

211

answers:

5

Hi, I am writing a program for formatting 100s of MB String data (nearing a gig) into xml == And I am required to return it as a response to an HTTP (GET) request .

I am using a StringWriter/XmlWriter to build an XML of the records in a loop and returning the

using (StringWriter writer = new StringWriter())
using (writer = XmlWriter.Create(writer, settings)) //where settings are the xml props

writer.ToString() 

during testing I saw a few --out of memory exceptions-- and quite clueless on how to find a solution? do you guys have any suggestions for a memory optimized delivery of the response?

is there a memory efficient way of encoding the data? or maybe chunking the data -- I just can not think of how to return it without building the whole thing into one HUGE string object

thanks

-- a few clarifications -- this is an asp .net webservices app over a gigabit ethernet link as josh noted. I am not very familiar with it so still a bit of a learning curve.

I am using XMLWriter to create the XML and create a string out of it using String

some stats -- response xml size = about 385 megs (my data size will grow very quickly to way more than this)

string object size as calculated by a memory profiler = peaked at 605MB

and thanks to everyone who responded...

A: 

You'll have to return each record (or a small group of records) on their own individual GETs.

Robert Harvey
+4  A: 

Use XmlTextWriter wrapped around Reponse.OutputStream to send the XML to the client and periodically flush the response. This way you never have to have more than a few mb in memory at any one time (at least for sending to the client).

Sam
It sounds like he's assembling the XML using string manipulation.
SLaks
@SLaks, Sounds like he could be doing anything since he really didn't say.
Sam
+1. Or even wrap around the `XmlTextWriter` around a `GZipStream` wrapped around `Response.OutputStream`.
Steven
+4  A: 

Can't you just stream the response to the client? XmlWriter doesn't require its underlying stream to be buffered in memory. If it's ASP.NET you can use the Response.OutputStream or if it's WCF, you can use response streaming.

Josh Einstein
Josh, this is a web services project -- client requests via GET to the web method -- being new to microsoft solutions, i am not sure if it is possible and how
bushman
It's probably not possible with ASMX web services and if that's what you're using I would highly suggest moving onto WCF now before it's too difficult to redesign. You've already run into one of ASMX's limitations and there's plenty of others not just limited to performance. But with WCF you can return a Stream object and chunk the data down to the caller. It's all built-in.
Josh Einstein
thanks josh!. great inputs from all but will mark this as the appropriate answer.
bushman
+1  A: 

HTTP get for 1 gig? that's a lot! Perhaps you should reconsider. At least gziping the output could help.

RC
Gzipping will not help if he's still building the XML this way. The problem is not in the transfer of the data, it's the fact that it's being buffered in memory before being sent. And there is no practical limit for a HTTP GET. Especially considering you can resume interrupted downloads and we have no idea what type of network he's sending it across. Could be a gigabit ethernet!
Josh Einstein
+1  A: 

You should not create XML using string manipulation.

Instead, you should use the XmlTextWriter, XmlDocument, or (in .Net 3.5) XElement classes to build an XML tree in memory, then write it directly to Response.OutputStream using an XmlTextWriter.

Writing directly to an XmlTextWriter that wraps Response.OutputStream wil be most efficient (you'll never have an entire element tree in memory at once), but will be somewhat more complicated.

By doing it this way, you will never have a single string (or array) containing the entire object, and should thus avoid OutOfMemoryExceptions.

SLaks
XmlDocument and XElement will exhibit the same (actually worse) memory issues than string manipulation! Building an XML structure that large can only be done with the XmlWriter API.
Josh Einstein
You can still get out of memory exceptions if you don't have enough contiguous memory. Changing the approach to write to a stream seems more reasonable.
Eric J.
@Josh: No. Only `String` and `Array` will allocate large blocks of _contiguous_ memory.
SLaks
Well that is true but the total memory consumed will be much larger for a XmlDocument/XElement than its string builder counterpart. Either way, holding that much data in memory is just asking for a DoS attack.
Josh Einstein
@Josh: Yes, but `XmlTextWriter` can be difficult to adapt to.
SLaks
No kidding. I hate that API. But when dealing with data of this size, the dev just needs to suck it up and do it the right way otherwise sh*t will just start breaking one day, usually right when you're in the middle of deploying that new billing system that's 6 months overdue.
Josh Einstein