<?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>Speaking of which... : OutOfMemory</title><link>http://blogs.msdn.com/johan/archive/tags/OutOfMemory/default.aspx</link><description>Tags: OutOfMemory</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>The KB article every one should know about</title><link>http://blogs.msdn.com/johan/archive/2007/05/23/the-kb-article-every-one-should-know-about.aspx</link><pubDate>Wed, 23 May 2007 18:23:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2817754</guid><dc:creator>JohanS</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/johan/comments/2817754.aspx</comments><wfw:commentRss>http://blogs.msdn.com/johan/commentrss.aspx?PostID=2817754</wfw:commentRss><description>&lt;p&gt;Have you read &lt;a href="http://support.microsoft.com/?kbid=307340"&gt;http://support.microsoft.com/?kbid=307340&lt;/a&gt;? If not, I suggest you do so. If you need convincing or simply want to know why this problem occurs I suggest you keep reading.&lt;/p&gt; &lt;p&gt;The problem described in the article above can cause your application to spike in CPU time, Memory usage or both. This will lead to your application hanging or possibly even crashing. The cause of the problem is&amp;nbsp;one of the most basic operations, and is something that we do very frequently.&lt;/p&gt; &lt;p&gt; &lt;hr&gt;  &lt;p&gt;&lt;/p&gt; &lt;h1&gt;The problem&lt;/h1&gt; &lt;p&gt;The problem in a nutshell is that string concatenation is bad. I don't mean bad as in "You shouldn't eat that extra piece of chocolate". I mean it as in "You really shouldn't put your head in wet concrete". If you've been reading my previous post on &lt;a href="http://blogs.msdn.com/johan/archive/2007/04/20/memory-management-in-the-net-framework.aspx"&gt;memory management&lt;/a&gt;&amp;nbsp;you might be able to figure out why string concatenation could be such a potential hazard. Consider the following scenario:&lt;/p&gt; &lt;p&gt;You're getting ready to go grocery shopping. You take a sheet of paper and a pen and begin writing down what you need to buy. The first item that crosses your mind is milk, so you write it down. Now you remember that you're out of bread as well, so you throw away the first sheet of paper, pick out a new one and write down milk and bread. You then throw away this paper too and write down milk, bread and&amp;nbsp;apples on a third piece of paper. You throw away the third piece of paper and repeat until finally the list is done. If you have 20 items on your list you now have 19 discarded papers lying on the floor waiting for the "garbage collector".&lt;/p&gt; &lt;p&gt;This is exactly how regular string concatenation works in .NET. Every time you concatenate a string the framework needs to allocate a new memory segment, large enough to hold the result of the concatenation and store the string in this new segment. The old segment is flagged as ready for garbage collection and as we all know garbage collection costs CPU and pending garbage collection costs memory.&lt;/p&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;A real&amp;nbsp;example&lt;/h1&gt; &lt;p&gt;So if you thought that 19 sheets of paper were a waste consider the following piece of code:&lt;/p&gt; &lt;div class="SampleCode"&gt;private String buildTable()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;String sReturn;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;int i, j;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;sReturn = "&amp;lt;table&amp;gt;"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (i = 0; i &amp;lt; 35; i++) // Rows&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sReturn += "&amp;lt;tr&amp;gt;"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (j = 0; j &amp;lt; 15; j++) // Columns&lt;br&gt;&amp;nbsp;&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;&amp;nbsp;&amp;nbsp;sReturn += "&amp;lt;td&amp;gt;"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sReturn += i.ToString() + " : " + j.ToString();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sReturn += "&amp;lt;/td&amp;gt;"&lt;br&gt;&amp;nbsp;&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;sReturn += "&amp;lt;/tr&amp;gt;"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;sReturn += "&amp;lt;/table&amp;gt;"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return sReturn;&lt;br&gt;} &lt;/div&gt; &lt;p&gt;All in all we have 2697 concatenations which means we have 2696 unnecessary allocations. The allocations will be gradually bigger and bigger, so the last ones will be almost as big as the final table. Needless to say this will consume a lot of unnecessary memory.&amp;nbsp;Also, if this table was built for a "real" application it would probably contain a lot more data for each cell, not to mention custom styles and classes. Imagine what would happen when the string goes past the magic &lt;a href="http://blogs.msdn.com/johan/archive/2007/04/20/memory-management-in-the-net-framework.aspx"&gt;85000 bytes barrier&lt;/a&gt; that defines what goes on the large object heap and what doesn't. In a larger scale this would have a &lt;em&gt;severe&lt;/em&gt; impact on performance.&lt;/p&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;This is a really weird behavior, how can it be?!&lt;/h1&gt; &lt;p&gt;It's not that odd really. If we extend the grocery shopping analogy a little we can see why there's a logical reason for this: You know that you want to write something down. You have a limited amount of paper, so what do you do? You cut out a piece of paper just large enough for you to write what you need. When you find that you need to add another item to the list you'll have to discard the old piece and cut out a new one. Not very practical, agreed, but you're trying to minimize your paper usage.&lt;/p&gt; &lt;p&gt;As the clever beings that we are we normally make a rough estimate of how big a piece of paper we need and then start writing. The framework, however, has no way of estimating how big a string is going to be. It doesn't know if you're going to concatenate it zero or ten thousand time, so that's something you'll have to estimate yourself.&lt;/p&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;So what should I do instead?&lt;/h1&gt; &lt;p&gt;One word: StringBuilder&lt;/p&gt; &lt;p&gt;The StringBuilder class is made especially for this type of operations. When using the StringBuilder class our sample above would look something like this&lt;/p&gt; &lt;div class="SampleCode"&gt;private String buildTableSB()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; StringBuilder sReturn = new StringBuilder();&lt;br&gt;&amp;nbsp;&amp;nbsp; sReturn.Capacity = 8000; // This is optional, but may be very efficient&lt;br&gt;&amp;nbsp;&amp;nbsp; int i, j;&lt;br&gt;&amp;nbsp;&amp;nbsp; sReturn.Append("&amp;lt;table&amp;gt;");&lt;br&gt;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; 35; i++) // Rows&lt;br&gt;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; sReturn.Append("&amp;lt;tr&amp;gt;");&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; for (j = 0; j &amp;lt; 15; j++) // Columns&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; sReturn.Append("&amp;lt;td&amp;gt;");&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; sReturn.Append(i.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; sReturn.Append(" : ");&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; sReturn.Append(j.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; sReturn.Append("&amp;lt;/td&amp;gt;");&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; sReturn.Append("&amp;lt;/tr&amp;gt;");&lt;br&gt;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp; sReturn.Append("&amp;lt;/table&amp;gt;");&lt;br&gt;&amp;nbsp;&amp;nbsp; return sReturn.ToString;&lt;br&gt;}&lt;/div&gt; &lt;p&gt;The difference in performance for a larger operation is enormous. I highly recommend trying out these samples. Copy the functions to a winforms/webforms application, increase the number of rows to 500 and run both versions. The&amp;nbsp;StringBuilder version will finish&amp;nbsp;within milliseconds, and the "classic" version will not...&amp;nbsp;For additional tidbits, take a look at the GC counter in performance monitor and look at how many GCs you have to make to complete the operation.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Bye for now / Johan&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2817754" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/johan/archive/tags/OutOfMemory/default.aspx">OutOfMemory</category><category domain="http://blogs.msdn.com/johan/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/johan/archive/tags/Managed+Heap/default.aspx">Managed Heap</category><category domain="http://blogs.msdn.com/johan/archive/tags/GC/default.aspx">GC</category><category domain="http://blogs.msdn.com/johan/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Memory management in the .NET Framework</title><link>http://blogs.msdn.com/johan/archive/2007/04/20/memory-management-in-the-net-framework.aspx</link><pubDate>Fri, 20 Apr 2007 16:07:29 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2206941</guid><dc:creator>JohanS</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/johan/comments/2206941.aspx</comments><wfw:commentRss>http://blogs.msdn.com/johan/commentrss.aspx?PostID=2206941</wfw:commentRss><description>&lt;p&gt;This is a subject that has been covered before and I have no intention of writing the ultimate post on the subject. Still I think this is something that every good developer should know.&lt;/p&gt; &lt;h1&gt;Why do I need to know this?&lt;/h1&gt; &lt;p&gt;My colleagues and I are quite often asked about the necessity of knowing how the Garbage Collector (GC) works. After all, it isn't really necessary to know what's going on behind the scenes, right..? A developer shouldn't have to bother about how the framework works..? Or should he..?&lt;/p&gt; &lt;p&gt;Well you may be a pretty good bus driver even if you know nothing about engines. Basic stuff like not stepping on the break and the gas at the same time is probably enough. If you want to do F1 racing, on the other hand, you will want to know as much as you can about your car. So, if you're content doing small scale web applications or not so efficient winforms applications, then you probably don't have to bother. If you want to do front-line work, then you've got to get your hands dirty.&lt;/p&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;The different generations&lt;/h1&gt; &lt;p&gt;In order to be effective the managed heap is trying to figure out which objects it can disregard and only check up on occasionally. Some objects may span the entire lifecycle of the application and others may be very short lived, so if an object stays alive for&amp;nbsp;a longer period of time the GC will check up on it less frequently. This is accomplished by dividing the&amp;nbsp;managed heap into three generations. Generations 0, 1 and 2.&amp;nbsp;An object will begin in generation 0 and if it is&amp;nbsp;in use for a long period of time it will travel through generations&amp;nbsp;0 to 2. A possible metaphor for this scenario would the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;You're asked to call a customer. You're pretty good with numbers&amp;nbsp;so you keep the phone number in your head.&amp;nbsp;(Generation 0)  &lt;li&gt;There is no reply and so you need to remember the phone number a little longer. Meanwhile you're given additional numbers to call.  &lt;li&gt;You know from past experience that your limit for keeping numbers in your head is 10, so once you reach that critical point you decide to write down the numbers you still&amp;nbsp;need on post-it notes (Generation 1)  &lt;li&gt;As the day goes on you keep transferring numbers from memory to post-its.  &lt;li&gt;Your desktop has now reached maximum capacity. It is cluttered with post-it notes, so you sort through them, determining which notes you still need. You throw away the ones&amp;nbsp;that are obsolete&amp;nbsp;and write down the remaining to your address book. (Generation 2)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Like I stated above; when an object is created it is put in Generation 0. The initial size limit of Generation 0 is determined by the size of the processor cache. This is dynamically changed depending on the allocation rate of the application. Once Generation 0 reaches its limit it will go through all the items in Generation 0, tag the obsolete objects for collection and remove them. This is called the Mark and Sweep phase. Everything that survives this sweep will be compacted and moved to Generation 1. The size limit of Generation 1 is also determined by the allocation rate of the application, and once it is reached a Generation 1 collection will occur. This will first mark and sweep all items in Generation 1, moving the surviving items to Generation 2, and then mark and sweep the items in Generation 0.&lt;/p&gt; &lt;p&gt;The healthy ratio between GC's in the different generations is approximately 100 - 10 - 1, so for 100 Generation 0 GC's you normally have 10 GC's of Generation 1 and 1 of Generation 2. A normal Generation 0 GC usually takes a few milliseconds. Performing a GC of Generation 1 rarely takes more than 30 milliseconds,&amp;nbsp;but a Generation 2 collection can take&amp;nbsp;quite some time depending on the application.&lt;/p&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;The Large Object Heap&lt;/h1&gt; &lt;p&gt;To top it off we also have what is called "The Large Object Heap" (LOH). This is where anything larger than 85.000 bytes will be stored. The&amp;nbsp;LOH is collected each time a new segment needs to be reserved (see below), but it is &lt;em&gt;not&lt;/em&gt; compacted like generations 0, 1 and 2. When you perform a collection on the LOH you will also perform a GC on the other generations.&lt;/p&gt; &lt;p&gt;Now, if the limit is at 85.000 bytes, won't most of my objects end up on the LOH? - Well not necessarily. For example: A dataset may contain lots and lots of data, but the dataset object only contains references to other objects. The data in the columns are each stored in individual strings and as long as they're not larger than 85 KB you're clear.&lt;/p&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;Memory segments&lt;/h1&gt; &lt;p&gt;The managed heap will reserve memory in segments. The size of the segments depend on the configuration. If &lt;span class="InlineCode"&gt;&amp;lt;gcServer enabled="true"/&amp;gt;&lt;/span&gt; you will reserve memory in 64 MB segments, otherwise you'll be doing it in 32 MB segments. LOH are reserved in 16 MB segments. Only Generation 2 and the LOH will span several segments.&lt;/p&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;What happens during GC?&lt;/h1&gt; &lt;p&gt;Let's say we're performing a full GC, including the LOH. This is what happens:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The objects on the LOH&amp;nbsp;are &lt;em&gt;Marked&lt;/em&gt;. Each item in the LOH is checked for references. If none are found it's ready to be collected.  &lt;li&gt;The LOH is &lt;em&gt;Swept&lt;/em&gt;. All marked objects are released from memory.  &lt;li&gt;The LOH is &lt;strong&gt;not&lt;/strong&gt; compacted.  &lt;li&gt;Generation 2 is &lt;em&gt;Marked.&lt;/em&gt;  &lt;li&gt;Generation 2 is &lt;em&gt;Swept.&lt;/em&gt;  &lt;li&gt;Generation 2 is compacted. (Imagine removing a few books from your bookcase, and then pushing the remaining books together freeing up continuous space at the end.)  &lt;li&gt;Generation 1 is &lt;em&gt;Marked.&lt;/em&gt;  &lt;li&gt;Generation 1 is &lt;em&gt;Swept.&lt;/em&gt; &lt;li&gt;Everything &amp;nbsp;that survived the sweep is compacted. &lt;li&gt;The pointer for where Generation 2 ends is updated. Everything that survived the sweep is now Generation 2. &lt;li&gt;Generation 0 is &lt;em&gt;Marked.&lt;/em&gt;  &lt;li&gt;Generation 0 is &lt;em&gt;Swept.&lt;/em&gt; &lt;li&gt;Everything that survived the sweep is compacted. &lt;li&gt;The pointer for where Generation 1 ends is updated. Everything that survived the sweep is now Generation 1.&lt;/li&gt;&lt;/ul&gt; &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;A few quick tips&lt;/h1&gt; &lt;p&gt;This topic could off course be a &lt;em&gt;lot&lt;/em&gt; bigger, but here are some quick suggestions.&lt;/p&gt; &lt;h2&gt;Try to stay out of Generation 1&lt;/h2&gt; &lt;p&gt;Well off course Generation 1 is better than Generation 2, but you should aim for keeping only a select few objects in Generation 2. Those should be variables that are defined at the beginning of the application lifecycle and released at the end. In an ideal world all other variables&amp;nbsp;should be of the hit-and-run variety and never leave Generation 0.&lt;/p&gt; &lt;h2&gt;Don't call GC.Collect()&lt;/h2&gt; &lt;p&gt;This has been said before. It will be said again, and again, and again. You should &lt;em&gt;almost&lt;/em&gt; never call GC.Collect() manually. And by &lt;em&gt;almost&lt;/em&gt; I mean once in a lifetime, not once per application, and certainly not once per function call. I occasionally call GC.Collect() for testing purposes just to see if memory has been released. Normally you would never call it. The GC is self-balancing and by calling GC.Collect() you are disrupting that balance. Think of it as tampering with the eco-system, pouring sugar in the gasoline or whatever metaphor you prefer. :-)&lt;/p&gt; &lt;h2&gt;Avoid large objects&lt;/h2&gt; &lt;p&gt;If you can stay below the 85.000 byte limit, then do so. If not, consider reusing the&amp;nbsp;object.&amp;nbsp;When it comes to large objects it's better&amp;nbsp;to use one for a long time than to use many for short periods of time.&lt;/p&gt; &lt;h2&gt;Don't use finalizers&lt;/h2&gt; &lt;p&gt;When your object has a finalizer the finalize method will be called when the object is no longer alive. So far so good. Unfortunately&amp;nbsp;your object will be passed into the next generation,&amp;nbsp;since it's not yet ready to be collected. This means that all objects with a finalizer will &lt;em&gt;at least&lt;/em&gt; end up in Generation 1. Most likely in Generation 2.&lt;/p&gt; &lt;p&gt;Well, as I said: There is a lot more to cover on this. There are books to be written and songs to be sung, but you've got to draw the line somewhere. I will most certainly cover more of this in future posts.&lt;/p&gt; &lt;p&gt;/ Johan&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2206941" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/johan/archive/tags/OutOfMemory/default.aspx">OutOfMemory</category><category domain="http://blogs.msdn.com/johan/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/johan/archive/tags/Managed+Heap/default.aspx">Managed Heap</category><category domain="http://blogs.msdn.com/johan/archive/tags/GC/default.aspx">GC</category><category domain="http://blogs.msdn.com/johan/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Why adding more memory won't resolve OutOfMemoryExceptions</title><link>http://blogs.msdn.com/johan/archive/2007/04/19/why-adding-more-memory-won-t-resolve-outofmemoryexceptions.aspx</link><pubDate>Thu, 19 Apr 2007 12:43:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2189486</guid><dc:creator>JohanS</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/johan/comments/2189486.aspx</comments><wfw:commentRss>http://blogs.msdn.com/johan/commentrss.aspx?PostID=2189486</wfw:commentRss><description>&lt;p&gt;&lt;/p&gt; &lt;p&gt;Quite often I am met with the incorrect assumption that out of memory exceptions can be resolved by adding more memory. I can understand why you'd think that, but actually it won't matter at all. Additional RAM may increase performance, but an additional 8GB of memory won't increase the available amount of memory for the .NET application.&lt;/p&gt; &lt;p&gt;Here's what you need to know:&lt;/p&gt; &lt;h2&gt;If you have a 32 bit machine then you have 2 GB of memory available.&lt;/h2&gt; &lt;p&gt;That's the way it is. Never mind if you have 512 MB or 8 GB of RAM. A 32-bit system can address 4 GB of virtual memory. 2 GB of those are reserved for the operating system, leaving 2 GB for each user mode process. If there is no RAM available we will use the page file and save infrequently used memory to disk instead. So additional RAM will cause fewer page faults, but the amount of memory available for the process is still only 2 GB.&lt;/p&gt; &lt;p&gt;(Actually you can tune this in boot.ini. There is a switch that will allow you to steal 1 GB from the OS and increase the limit for the user process from 2 GB to 3 GB. It still requires some additional tweaking though. I suggest looking at &lt;a href="http://support.microsoft.com/kb/820108/en-us"&gt;http://support.microsoft.com/kb/820108/en-us&lt;/a&gt;&amp;nbsp;for more information on this.)&lt;/p&gt; &lt;p&gt;Okay, so now that we know this it's time for the next vital piece of information:&lt;/p&gt; &lt;h2&gt;Your process will most likely be out of memory when it reaches ~800 MB&lt;/h2&gt; &lt;p&gt;- What!? How is that possible!? Didn't I just say that we have 2 GB available? I did, but there is another thing you really need to know about memory allocations:&lt;/p&gt; &lt;h2&gt;Memory allocations need to be continuous.&lt;/h2&gt; &lt;p&gt;If you want to allocate a 100 MB string, then you need 100 MB of &lt;em&gt;continuous&lt;/em&gt; space. Memory allocations don't work the way the file system does.&amp;nbsp;If we were talking about files we could save part of the file in one place, another part in another place, etc. but memory != file system. Open up the disk defragmenter and take a look at your hard drive. You may have 100 GB available on your 250 GB hard drive, but how much of that is continuous? The available memory for your process will eventually become just as fragmented as your hard drive. And as your memory becomes more and more fragmented it will be harder and harder to squeeze in those large allocations.&lt;/p&gt; &lt;p&gt;Let's say you and your party of four walk into a restaurant. The restaurant is packed with four seat tables so finding a seat shouldn't be a problem. Unfortunately there is 1-3 persons sitting at each table. So even if only half the seats are taken you are still unable to get your own table. The usher gets an OutOfSeatsException as he tries to seat you. :-)&lt;/p&gt; &lt;p&gt;The rule of thumb is that you'll begin seeing OutOfMemoryExceptions at around 800 MB. Off course this isn't set in stone. It&amp;nbsp;depends entirely on the average size of the objects you allocate and how fragmented your memory becomes. You might make it up to 1.2 GB or you might see the exceptions already at 550 MB.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h1&gt;So what can be done?&lt;/h1&gt; &lt;p&gt;Well if you're in the planning stage of a WebService that will load 4 GB images, process them somehow and then return them to the client you'll want to either:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Work with streams and make sure you never load the full image into memory&lt;/li&gt; &lt;li&gt;Set aside the money to invest in a 64 bit system&lt;/li&gt; &lt;li&gt;Rethink&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;I'm currently writing a bigger post on how the managed heap and garbage collector work, so expect more to come on the subject.&lt;/p&gt; &lt;p&gt;/ Johan&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2189486" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/johan/archive/tags/OutOfMemory/default.aspx">OutOfMemory</category><category domain="http://blogs.msdn.com/johan/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/johan/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>I am getting OutOfMemoryExceptions. How can I troubleshoot this?</title><link>http://blogs.msdn.com/johan/archive/2007/01/11/i-am-getting-outofmemoryexceptions-how-can-i-troubleshoot-this.aspx</link><pubDate>Thu, 11 Jan 2007 19:46:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1451030</guid><dc:creator>JohanS</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/johan/comments/1451030.aspx</comments><wfw:commentRss>http://blogs.msdn.com/johan/commentrss.aspx?PostID=1451030</wfw:commentRss><description>&lt;h1&gt;Problem:&lt;/h1&gt; &lt;p&gt;You've written an ASP.NET application that is getting OutOfMemoryExceptions.&lt;/p&gt; &lt;h1&gt;Cause:&lt;/h1&gt; &lt;p&gt;Let's find out...&lt;/p&gt; &lt;h1&gt;Resolution:&lt;/h1&gt; &lt;p&gt;Use Windbg to take a look at the heap.&lt;/p&gt; &lt;hr&gt;  &lt;h1&gt;&amp;nbsp;&lt;/h1&gt; &lt;h1&gt;Is it a leak?&lt;/h1&gt; &lt;p&gt;Take a look at the memory usage of you application using perfmon. If memory is slowly increasing and never released, then you have a leak. If it is going up and down like a rollercoaster, then you are most likely using huge amounts of memory for certain operations which is later garbage collected.&lt;/p&gt; &lt;h1&gt;How do I troubleshoot this?&lt;/h1&gt; &lt;p&gt;Below I'll try to give you a step by step description of how to troubleshoot this scenario&lt;/p&gt; &lt;h2&gt;1. Get a memory dump&lt;/h2&gt; &lt;p&gt;This is done using Windbg and Adplus. If you don't have Windbg installed, check out my &lt;a href="http://blogs.msdn.com/johan/archive/2007/01/11/how-to-install-windbg-and-get-your-first-memory-dump.aspx"&gt;previous post&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; &lt;h2&gt;2. Open up the dump and load SOS&lt;/h2&gt; &lt;p&gt;Open the dump in Windbg and load the SOS extension. You'll find it in the framework directory so if you're debugging an application for Framework 2.0 look in "C:\Windows\Microsoft.NET\Framework\v2.0.50727". Anyway, load SOS by typing:&lt;/p&gt; &lt;div class="SampleCode"&gt;.load [path]\sos&lt;/div&gt; &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; &lt;h2&gt;3. Run dumpheap&lt;/h2&gt; &lt;p&gt;Execute the following command:&lt;/p&gt; &lt;div class="SampleCode"&gt;!dumpheap -stat&lt;/div&gt; &lt;p&gt;It will show statistics for the objects on the heap in a nice little summary divided in tho four columns.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;The method table of the object  &lt;li&gt;The number of objects of this type on the heap  &lt;li&gt;The total size of these objects in bytes  &lt;li&gt;The name of the object type&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Be careful not to omit the -stat parameter. If you do then Windbg will dump the address of each object in the entire heap to your screen, which will be a lot of information to say the least.&lt;/p&gt; &lt;h1&gt;Analyzing the information provided by !dumpheap&lt;/h1&gt; &lt;p&gt;Here's a sample heap from one of my cases... &lt;/p&gt; &lt;div class="SampleCode"&gt;0:000&amp;gt; !dumpheap -stat&lt;br&gt;Statistics:&lt;br&gt;MT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Count &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TotalSize Class Name&lt;br&gt;7a787cc4&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12 System.IO.FileSystemWatcher+FSWAsyncResult&lt;br&gt;7a75904c &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;1 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12 System.Diagnostics.OrdinalCaseInsensitiveComparer&lt;br&gt;7a7575cc &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12 System.CodeDom.Compiler.CodeDomConfigurationHandler&lt;br&gt;7a7571a8 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12 System.Net.DefaultCertPolicy&lt;br&gt;7a75661c &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; 12 System.Diagnostics.TraceListenerCollection&lt;br&gt;7a755834 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; 12 System.Diagnostics.PerformanceCounterCategoryType&lt;br&gt;........CONTINUED.........&lt;br&gt;68a66a88&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 227,559&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;12,743,304 System.Web.UI.WebControls.Literal&lt;br&gt;68a2f7fc &amp;nbsp;&amp;nbsp;&amp;nbsp; 399,272 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;14,373,792 System.Web.UI.ControlCollection&lt;br&gt;68a92e2c &amp;nbsp;&amp;nbsp;&amp;nbsp; 768,731 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;33,824,164 System.Web.UI.Control+OccasionalFields&lt;br&gt;68a884a0 &amp;nbsp;&amp;nbsp;&amp;nbsp; 641,952 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;38,517,120 System.Web.UI.LiteralControl&lt;br&gt;79124228 &amp;nbsp;&amp;nbsp;&amp;nbsp; 879,515 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;43,394,976 System.Object[]&lt;br&gt;790fa3e0&amp;nbsp;&amp;nbsp;&amp;nbsp;1,431,594&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 122,806,484 System.String&lt;br&gt;&lt;br&gt;Total 10,389,625 objects, Total size: 463,313,540 &lt;/div&gt; &lt;p&gt;So in this particular dump I have 1,431,594 strings whose total size is 122 MBytes, 879,515 Objects with a total size of&amp;nbsp;43 MBytes, etc.&lt;/p&gt; &lt;h2&gt;Objects in heap may be larger than they appear&lt;/h2&gt; &lt;p&gt;The TotalSize column isn't 100% true. Look at the LiteralControls that are on third place. They only use a total of 38 MBytes, or do they? The TotalSize refers to the object structure, but the member variables like strings, integers and other&amp;nbsp;child objects are not included. It kind of makes sense, since otherwise the Total size would be completely off the scale. The LiteralControl objects contain a number of child objects and three of those are strings. Their respective size is listed with the System.String object.&lt;/p&gt; &lt;h2&gt;Using !dumpobj&lt;/h2&gt; &lt;p&gt;Let's take a closer look at one of the System.Web.UI.LiteralControls. We list all of the controls with the following command &lt;span class="InlineCode"&gt;!dumpheap -type System.Web.UI.LiteralControl&lt;/span&gt; and quickly press Ctrl+Break before the screen fills with too many lines:&lt;/p&gt; &lt;div class="SampleCode"&gt;0:000&amp;gt; !dumpheap -type System.Web.UI.LiteralControl&lt;br&gt;&amp;nbsp;Address&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MT Size Gen&lt;br&gt;023ea0a8 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023ea0e4 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023ea374 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023ea460 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023ea510 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023eab3c 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;........CONTINUED........&lt;br&gt;023fe31c 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023fe414 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023fe4c4 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;br&gt;023fe500 68a884a0&amp;nbsp;&amp;nbsp; 60&amp;nbsp;&amp;nbsp; 2 System.Web.UI.LiteralControl &lt;/div&gt; &lt;p&gt;As you can see each LiteralControl is 60 bytes in size. Like I said before that's the size of the object structure alone, not it's referenced objects and properties. We now pick the address of one of the LiteralControls and execute the &lt;span class="InlineCode"&gt;!dumpobj&lt;/span&gt; command (&lt;span class="InlineCode"&gt;!do&lt;/span&gt; for short). This gives us the following result:  &lt;div class="SampleCode"&gt;0:000&amp;gt; !do 023ea0a8 &lt;br&gt;Name: System.Web.UI.LiteralControl&lt;br&gt;MethodTable: 68a884a0&lt;br&gt;EEClass: 68a88428&lt;br&gt;Size: 60(0x3c) bytes&lt;br&gt;GC Generation: 2&lt;br&gt;(C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)&lt;br&gt;Fields:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MT&amp;nbsp;&amp;nbsp;&amp;nbsp; Field Offset&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type&amp;nbsp;&amp;nbsp; VT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Attr&amp;nbsp;&amp;nbsp;&amp;nbsp; Value Name&lt;br&gt;790fa3e0&amp;nbsp; 4001fe0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.String&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0 instance 00000000 _id&lt;br&gt;790fa3e0&amp;nbsp; 4001fe1&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 instance 00000000 _cachedUniqueID&lt;br&gt;68a2af44&amp;nbsp; 4001fe2&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; c&amp;nbsp;&amp;nbsp; ...em.Web.UI.Control&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0 instance 023e8864 _parent&lt;br&gt;68a91070&amp;nbsp; 4001fe3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Int32&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0 instance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 _controlState&lt;br&gt;68a85ea0&amp;nbsp; 4001fe4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&amp;nbsp;&amp;nbsp; ...m.Web.UI.StateBag&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 instance 00000000 _viewState&lt;br&gt;68a2af44&amp;nbsp; 4001fe5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 14&amp;nbsp;&amp;nbsp; ...em.Web.UI.Control&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 instance 023e8864 _namingContainer&lt;br&gt;68a273d0&amp;nbsp; 4001fe6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 18&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.UI.Page&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0 instance 01df4514 _page&lt;br&gt;68a92e2c&amp;nbsp; 4001fe7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1c&amp;nbsp;&amp;nbsp; ...+OccasionalFields&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 instance 00000000 _occasionalFields&lt;br&gt;68a2b378&amp;nbsp; 4001fe8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 20&amp;nbsp;&amp;nbsp; ...I.TemplateControl&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 instance 00000000 _templateControl&lt;br&gt;68a14528&amp;nbsp; 4001fe9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&amp;nbsp;&amp;nbsp; ...m.Web.VirtualPath&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 instance 00000000 _templateSourceVirtualDirectory&lt;br&gt;68a8bb48&amp;nbsp; 4001fea&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;28&amp;nbsp;&amp;nbsp; ...rs.ControlAdapter&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 instance 00000000 _adapter&lt;br&gt;68a3a8f8&amp;nbsp; 4001feb&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;30&amp;nbsp;&amp;nbsp; ...SimpleBitVector32&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 instance 023ea0d8 flags&lt;br&gt;790f9c18&amp;nbsp; 4001fda&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c70&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Object&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp;&amp;nbsp;shared&amp;nbsp;&amp;nbsp;&amp;nbsp;static EventDataBinding&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:NotInit 0011a720:01df0028 &amp;lt;&amp;lt;&lt;br&gt;790f9c18&amp;nbsp; 4001fdb&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c74&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Object&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp;&amp;nbsp;static EventInit&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:NotInit 0011a720:01df0034 &amp;lt;&amp;lt;&lt;br&gt;790f9c18&amp;nbsp; 4001fdc&amp;nbsp;&amp;nbsp;&amp;nbsp; c78&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Object&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp;&amp;nbsp;static EventLoad&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:NotInit 0011a720:01df0040 &amp;lt;&amp;lt;&lt;br&gt;790f9c18&amp;nbsp; 4001fdd&amp;nbsp;&amp;nbsp;&amp;nbsp; c7c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Object&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp; static EventUnload&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:NotInit 0011a720:01df004c &amp;lt;&amp;lt;&lt;br&gt;790f9c18&amp;nbsp; 4001fde&amp;nbsp;&amp;nbsp;&amp;nbsp; c80&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Object&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp; static EventPreRender&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:NotInit 0011a720:01df0058 &amp;lt;&amp;lt;&lt;br&gt;790f9c18&amp;nbsp; 4001fdf&amp;nbsp;&amp;nbsp;&amp;nbsp; c84&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Object&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp; static EventDisposed&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:NotInit 0011a720:01df0064 &amp;lt;&amp;lt;&lt;br&gt;79124228&amp;nbsp; 4001fec&amp;nbsp;&amp;nbsp;&amp;nbsp; c88&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Object[]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp; static automaticIDs&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:NotInit 0011a720:01df0070 &amp;lt;&amp;lt;&lt;br&gt;790fa3e0&amp;nbsp; 4002211&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 34&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.String&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0 instance 02238664 _text &lt;/div&gt; &lt;p&gt;Cool, now we can take a look at the specifics. For example the value of the text-property, which is located in the string down at the bottom with address 02238664. To get it's value, simply perform a &lt;span class="InlineCode"&gt;!do&lt;/span&gt; on the address:  &lt;div class="SampleCode"&gt;0:000&amp;gt; !do 02238664 &lt;br&gt;Name: System.String&lt;br&gt;MethodTable: 790fa3e0&lt;br&gt;EEClass: 790fa340&lt;br&gt;Size: 158(0x9e) bytes&lt;br&gt;GC Generation: 2&lt;br&gt;(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)&lt;br&gt;String:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/td&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/tr&amp;gt;&lt;br&gt;&amp;nbsp; &amp;lt;/table&amp;gt;&lt;br&gt;&amp;lt;!-- end&amp;nbsp;of&amp;nbsp;content table&amp;nbsp;--&amp;gt; &lt;br&gt;&amp;nbsp;&lt;br&gt;Fields:&lt;br&gt;MT Field Offset Type VT Attr Value Name&lt;br&gt;790fed1c 4000096 4 System.Int32 0 instance 71 m_arrayLength&lt;br&gt;790fed1c 4000097 8 System.Int32 0 instance 70 m_stringLength&lt;br&gt;790fbefc 4000098 c System.Char 0 instance 3c m_firstChar&lt;br&gt;790fa3e0 4000099 10 System.String 0 shared static Empty&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:790d6584 0011a720:790d6584 &amp;lt;&amp;lt;&lt;br&gt;79124670 400009a 14 System.Char[] 0 shared static WhitespaceChars&lt;br&gt;&amp;gt;&amp;gt; Domain:Value 000f0d00:01d413b8 0011a720:01d44f80 &amp;lt;&amp;lt; &lt;/div&gt; &lt;p&gt;Okay, so we can see that the string contains some data to close off a table.&amp;nbsp;We can also take a look at the other properties for the object and examine them if we wish. But there is another command that is really useful...  &lt;h2&gt;Using !objsize&lt;/h2&gt; &lt;p&gt;Is there a way to get the total size of a specific System.Web.UI.LiteralControl? - Simple! We use the &lt;span class="InlineCode"&gt;!objsize &lt;/span&gt;-command. !objsize looks at all the pointers within an object and calculate their total size. Below is the built in documentation for the !objsize -command:  &lt;div class="SampleCode"&gt;0:000&amp;gt; !help objsize&lt;br&gt;-------------------------------------------------------------------------------&lt;br&gt;!ObjSize [&amp;lt;Object address&amp;gt;] &lt;br&gt;&amp;nbsp;&lt;br&gt;With no parameters, !ObjSize lists the size of all objects found on managed &lt;br&gt;threads. It also enumerates all GCHandles in the process, and totals the size &lt;br&gt;of any objects pointed to by those handles. In calculating object size, &lt;br&gt;!ObjSize includes the size of all child objects in addition to the parent. &lt;br&gt;&amp;nbsp;&lt;br&gt;For example, !DumpObj lists a size of 20 bytes for this Customer object: &lt;br&gt;&amp;nbsp;&lt;br&gt;0:000&amp;gt; !do a79d40&lt;br&gt;Name: Customer&lt;br&gt;MethodTable: 009038ec&lt;br&gt;EEClass: 03ee1b84&lt;br&gt;Size: 20(0x14) bytes&lt;br&gt;(C:\pub\unittest.exe)&lt;br&gt;Fields:&lt;br&gt;MT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Field Offset&amp;nbsp; Type&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; Attr&amp;nbsp;&amp;nbsp;&amp;nbsp; Value&amp;nbsp;&amp;nbsp;Name&lt;br&gt;009038ec 4000008&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4 CLASS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance 00a79ce4&amp;nbsp;&amp;nbsp;name&lt;br&gt;009038ec 4000009&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8 CLASS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance 00a79d2c&amp;nbsp; bank&lt;br&gt;009038ec 400000a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c System.Boolean instance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 valid &lt;br&gt;&amp;nbsp;&lt;br&gt;but !ObjSize lists 152 bytes:&lt;br&gt;0:000&amp;gt; !ObjSize a79d40&lt;br&gt;sizeof(00a79d40) = 152 ( 0x98) bytes (Customer) &lt;br&gt;&amp;nbsp;&lt;br&gt;This is because a Customer points to a Bank, has a name, and the Bank points to&lt;br&gt;an Address string. You can use !ObjSize to identify any particularly large &lt;br&gt;objects, such as a managed cache in a web server. &lt;/div&gt; &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; &lt;h2&gt;Objects in heap may also be &lt;em&gt;smaller &lt;/em&gt;than they appear&lt;/h2&gt; &lt;p&gt;So what do we get if we run !objsize on our LiteralControl? This is really interesting, because what happens is; the debugger gets really busy for quite some time and eventually we get this:&lt;/p&gt; &lt;div class="SampleCode"&gt;0:000&amp;gt; !objsize 023ea0a8 &lt;br&gt;sizeof(023ea0a8) = 456918136 ( 0x1b3c0478) bytes (System.Web.UI.LiteralControl)&lt;/div&gt; &lt;p&gt;456 MBytes! How is that possible? Well&amp;nbsp;if you scroll up to where we&amp;nbsp;ran the !do command on the&amp;nbsp;LiteralControl, you'll see that the control holds a reference to the page. The&amp;nbsp;page in turn has a reference to the cache, and before long we'll have&amp;nbsp;referenced almost the entire heap.&lt;/p&gt; &lt;h1&gt;Summary&lt;/h1&gt; &lt;p&gt;Hopefully this is enough to give you a quick glimpse of what is possible with three relatively simple commands from the sos extension. The commands were:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;!dumpheap  &lt;li&gt;!dumpobj  &lt;li&gt;!objsize&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Over and out&lt;/p&gt; &lt;p&gt;/ Johan&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1451030" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/johan/archive/tags/OutOfMemory/default.aspx">OutOfMemory</category><category domain="http://blogs.msdn.com/johan/archive/tags/WinDbg/default.aspx">WinDbg</category><category domain="http://blogs.msdn.com/johan/archive/tags/GC/default.aspx">GC</category></item><item><title>Are you getting OutOfMemoryExceptions when uploading large files?</title><link>http://blogs.msdn.com/johan/archive/2006/11/15/are-you-getting-outofmemoryexceptions-when-uploading-large-files.aspx</link><pubDate>Wed, 15 Nov 2006 12:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1080526</guid><dc:creator>JohanS</dc:creator><slash:comments>30</slash:comments><comments>http://blogs.msdn.com/johan/comments/1080526.aspx</comments><wfw:commentRss>http://blogs.msdn.com/johan/commentrss.aspx?PostID=1080526</wfw:commentRss><description>&lt;H1&gt;Problem:&lt;/H1&gt;
&lt;P&gt;Using the WebClient.Upload method for posting large files will eventually leave you stranded with OutOfMemoryExceptions.&lt;/P&gt;
&lt;H1&gt;Cause:&lt;/H1&gt;
&lt;P&gt;WebClient.Upload reads the entire file to memory by default.&lt;/P&gt;
&lt;H1&gt;Resolution:&lt;/H1&gt;
&lt;P&gt;Build your own uploader.&lt;/P&gt;
&lt;HR&gt;

&lt;H1&gt;Scenario:&lt;/H1&gt;
&lt;P mce_keep="true"&gt;One of my customers was using &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;WebClient.Upload&lt;/SPAN&gt; in a Winforms application to transfer files to a webserver. The idea in itself was fine, but when they transferred a couple of large files they'd get OutOfMemoryExceptions.&amp;nbsp;When uploading a 500 MB file the application would need&amp;nbsp;approximately 520 MB of memory and if you uploaded&amp;nbsp;a few&amp;nbsp;large files&amp;nbsp;after each other you quickly hit the roof. Running &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;GC.Collect();&lt;/SPAN&gt; after each transfer didn't help.&amp;nbsp;Judging from the number of hits on the internet for this scenario they weren't the only ones with this problem.&lt;/P&gt;
&lt;P mce_keep="true"&gt;This is the code they were using:&lt;/P&gt;
&lt;DIV class=SampleCode&gt;
&lt;P mce_keep="true"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;WebClient&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; oWeb = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;WebClient&lt;/SPAN&gt;();&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;oWeb.UploadFile(&lt;SPAN style="COLOR: maroon"&gt;"http://localhost/test.aspx"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: maroon"&gt;"c:\\bigfile.cab"&lt;/SPAN&gt;);&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P mce_keep="true"&gt;Okay, so why was this&amp;nbsp;happening?&lt;BR&gt;Well, first of all I wouldn't recommend running &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;GC.Collect();&lt;/SPAN&gt; in any application. A lot has been written on this allready, but if you're interested in why I suggest you look at &lt;A class="" href="http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx" target=_blank mce_href="http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx"&gt;Rico Mariani's post on the subject&lt;/A&gt;. Anyway, for testing purposes we ran the following instead:&lt;/P&gt;
&lt;DIV class=SampleCode&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;GC&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.Collect(3);&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: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;GC&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.WaitForPendingFinalizers();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;GC&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.Collect(3);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P mce_keep="true"&gt;And&amp;nbsp;this cleared the memory.&amp;nbsp;So why isn't this a valid solution? Well, like I said, I wouldn't recommend&amp;nbsp;using&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;GC.Collect();&lt;/SPAN&gt; in any application, and why read the entire file to memory when you can&amp;nbsp;stream it? I looked up the UploadFile-method and it seems like it does read the entire file to a byte array before posting. This is great for smaller files, but in this particular scenario it wasn't too good. So what I did was to write my own uploader:&lt;/P&gt;
&lt;DIV class=SampleCode&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; MyUploader(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; strFileToUpload, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; strUrl)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt; 
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; strFileFormName = &lt;SPAN style="COLOR: maroon"&gt;"file"&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;Uri&lt;/SPAN&gt; oUri = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;Uri&lt;/SPAN&gt;(strUrl);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; strBoundary = &lt;SPAN style="COLOR: maroon"&gt;"----------"&lt;/SPAN&gt; + &lt;SPAN style="COLOR: teal"&gt;DateTime&lt;/SPAN&gt;.Now.Ticks.ToString(&lt;SPAN style="COLOR: maroon"&gt;"x"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// The trailing boundary string&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;byte&lt;/SPAN&gt;[] boundaryBytes = &lt;SPAN style="COLOR: teal"&gt;Encoding&lt;/SPAN&gt;.ASCII.GetBytes(&lt;SPAN style="COLOR: maroon"&gt;"\r\n--"&lt;/SPAN&gt; + strBoundary + &lt;SPAN style="COLOR: maroon"&gt;"\r\n"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// The post message header&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;StringBuilder&lt;/SPAN&gt; sb = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;StringBuilder&lt;/SPAN&gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"--"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(strBoundary);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"\r\n"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"Content-Disposition: form-data; name=\""&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(strFileFormName);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"\"; filename=\""&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: teal"&gt;Path&lt;/SPAN&gt;.GetFileName(strFileToUpload));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"\""&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"\r\n"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"Content-Type: "&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"application/octet-stream"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"\r\n"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;sb.Append(&lt;SPAN style="COLOR: maroon"&gt;"\r\n"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; strPostHeader = sb.ToString();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;byte&lt;/SPAN&gt;[] postHeaderBytes = &lt;SPAN style="COLOR: teal"&gt;Encoding&lt;/SPAN&gt;.UTF8.GetBytes(strPostHeader);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// The WebRequest&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;HttpWebRequest&lt;/SPAN&gt; oWebrequest = (&lt;SPAN style="COLOR: teal"&gt;HttpWebRequest&lt;/SPAN&gt;)&lt;SPAN style="COLOR: teal"&gt;WebRequest&lt;/SPAN&gt;.Create(oUri);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;oWebrequest.ContentType = &lt;SPAN style="COLOR: maroon"&gt;"multipart/form-data; boundary="&lt;/SPAN&gt; + strBoundary;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;oWebrequest.Method = &lt;SPAN style="COLOR: maroon"&gt;"POST"&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// This is important, otherwise the whole file will be read to memory anyway...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;oWebrequest.AllowWriteStreamBuffering = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Get a FileStream and set the final properties of the WebRequest&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;FileStream&lt;/SPAN&gt; oFileStream = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;FileStream&lt;/SPAN&gt;(strFileToUpload, &lt;SPAN style="COLOR: teal"&gt;FileMode&lt;/SPAN&gt;.Open, &lt;SPAN style="COLOR: teal"&gt;FileAccess&lt;/SPAN&gt;.Read);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;long&lt;/SPAN&gt; length = postHeaderBytes.Length + oFileStream.Length + boundaryBytes.Length;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;oWebrequest.ContentLength = length;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;Stream&lt;/SPAN&gt; oRequestStream = oWebrequest.GetRequestStream();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Write the post header&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;oRequestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Stream the file contents in small pieces (4096 bytes, max).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;byte&lt;/SPAN&gt;[] buffer = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;Byte&lt;/SPAN&gt;[&lt;SPAN style="COLOR: blue"&gt;checked&lt;/SPAN&gt;((&lt;SPAN style="COLOR: blue"&gt;uint&lt;/SPAN&gt;)&lt;SPAN style="COLOR: teal"&gt;Math&lt;/SPAN&gt;.Min(4096, (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)oFileStream.Length))];&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; bytesRead = 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;while&lt;/SPAN&gt; ((bytesRead = oFileStream.Read(buffer, 0, buffer.Length)) != 0)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; 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; &lt;/SPAN&gt;oRequestStream.Write(buffer, 0, bytesRead);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;oFileStream.Close();&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add the trailing boundary&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;oRequestStream.Write(boundaryBytes, 0, boundaryBytes.Length);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;WebResponse&lt;/SPAN&gt; oWResponse = oWebrequest.GetResponse();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;Stream&lt;/SPAN&gt; s = oWResponse.GetResponseStream();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: teal"&gt;StreamReader&lt;/SPAN&gt; sr = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;StreamReader&lt;/SPAN&gt;(s);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;String&lt;/SPAN&gt;&amp;nbsp;sReturnString = sr.ReadToEnd();&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;Clean up&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: green"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; oFileStream.Close();&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; oRequestStream.Close();&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; s.Close();&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sr.Close();&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; sReturnString;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;One of the things worth noting is that you need to set&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;oWebrequest.AllowWriteStreamBuffering = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;/o:p&gt;Otherwise you will read the entire file to memory anyway. This is because the default behavior of the WebRequest is to buffer the entire request in case it needs to re-send it due to authentication, connectivity problems, etc. Again, this is a default behavior that normally is a performance boost, but in this case is a performance killer. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;So what was the end result?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none" mce_keep="true"&gt;During my first test runs the application needed as much memory as the file I was trying to upload, and then some. So in order to upload a 500 MB .cab-file the application needed at least 520 MB. The application using the custom uploader never went above 23 MB.&lt;/P&gt;
&lt;P mce_keep="true"&gt;End of transmission&lt;/P&gt;
&lt;P mce_keep="true"&gt;/ Johan&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1080526" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/johan/archive/tags/Upload/default.aspx">Upload</category><category domain="http://blogs.msdn.com/johan/archive/tags/Stream/default.aspx">Stream</category><category domain="http://blogs.msdn.com/johan/archive/tags/OutOfMemory/default.aspx">OutOfMemory</category><category domain="http://blogs.msdn.com/johan/archive/tags/WebClient/default.aspx">WebClient</category><category domain="http://blogs.msdn.com/johan/archive/tags/Performance/default.aspx">Performance</category></item></channel></rss>