Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
OutOfMemory and StringBuilder
Message
From
12/01/2013 11:24:00
 
 
General information
Forum:
ASP.NET
Category:
Troubleshooting
Environment versions
Environment:
VB 9.0
OS:
Windows 7
Network:
Windows 2003 Server
Database:
MS SQL Server
Application:
Web
Miscellaneous
Thread ID:
01562245
Message ID:
01562311
Views:
30
>>>>>>>I have four worker process answering the Web site. On one specific option a user did on the Web site, this has triggered a very long SQL command on SQL Server resulting in that process ID to take pretty much 100% of the memory available to it.
>>>>>>>
>>>>>>>Until we stopped that process, we ended up with several errors like this:
>>>>>>>
>>>>>>>"Exception of type 'System.OutOfMemoryException' was thrown."
>>>>>>>
>>>>>>>When looking at the trace, it was normal to see that the trace was pretty much different for each of them as, when there is no more memory available to process a transaction, an error can happen everywhere.
>>>>>>>
>>>>>>>However, what I do not understand, is one of them has this scenario. The Stack Trace ends up with at System.Text.StringBuilder.ToString() as the last item in it. This is from this method:
>>>>>>>
>>>>>>>
>>>>>>>        ' Equivalent of VFP StrTran()
>>>>>>>        ' expC1 String
>>>>>>>        ' expC2 Search for specific character
>>>>>>>        ' expC3 Replace
>>>>>>>        Public Function StrTran(ByVal tcSearchIn As String, ByVal tcSearchFor As String, _
>>>>>>>         ByVal tcReplace As String) As String
>>>>>>>            Dim loStringBuilder As StringBuilder = New StringBuilder(tcSearchIn)
>>>>>>>            Return loStringBuilder.Replace(tcSearchFor, tcReplace).ToString()
>>>>>>>        End Function
>>>>>>>
>>>>>>>
>>>>>>>So, basically, because of a memory issue, the StringBuilder was not able to execute. However, as surprisingly as it gets, the insert into SQL Server to log this error worked.
>>>>>>>
>>>>>>>So, can anyone explain me why a simple command like that could trigger a 'System.OutOfMemoryException' when, at the same time, after it failed at that location, I was able to execute an insert into SQL Server?
>>>>>>
>>>>>>
>>>>>>Michel,
>>>>>>
>>>>>>Not an answer to your question, but why do you use a StringBuilder() when you can do without ?
>>>>>>
>>>>>>I think this should be sufficient as the only statement of the method
>>>>>>
>>>>>>return tcSearchIn.Replace(tcSearchFor, tcReplace)
>>>>>>
>>>>>>
>>>>>>Your approach creates a StringBuilder object, which creates a char array and both the char array and the StringBuilder have to be garbage collected at some point
>>>>>>
>>>>>>No big deal, but I couldn't help telling you
>>>>>
>>>>>I thought StringBiulder.Replace() was more efficient (especially if the result is a shorter string)
>>>>
>>>>Dunno about StringBuilder.Replace being more efficient - never tested that
>>>>But my point is - why do all the following steps when you can avoid them ?
>>>>
>>>>(1) Creating an new object
>>>>(2) the object creates a char array
>>>>(3) the string is copied into the char array
>>>>(4) the char array and the object have to be garbage collected afterwards
>>>>
>>>>>How about passing the strings by ref and using StringBuilder() ?
>>>>Don't think that this will help - since string is a reference type
>>>>
>>>>
>>>>Update - Using StringBuilder is more efficient when you have to do a number of changes to a string since each change yields a new string
>>>>But for 3 or 4 changes I think not using stringBuilder is the more efficient ( Also depends on the size of the string)
>>>>And for one update I don't even consider using StringBuilder
>>>
>>>I take your point. So if StringBuilder() is not being used there's no point in the function anyway.
>>>
>>>Now I wonder how String.Replace() works internally - might that also be creating an array to do the job ?
>>
>>Good question - I wonder myself
>>
>>You can find out for yourself - download the sources here http://referencesource.microsoft.com/netframework.aspx
>>I just downloaded some of them
>>
>>(A) Net 4.5
>>
>>(1) StringBuilder definitely uses a char[] - which I expected
>>
>>(2)
>>
>>I had a look at the source code of String
>>
>>       public String Replace(String oldValue, String newValue) 
>>        {
>>            if (oldValue == null) 
>>                throw new ArgumentNullException("oldValue");
>>            // Note that if newValue is null, we treat it like String.Empty.
>>            Contract.Ensures(Contract.Result<String>() != null);
>>            Contract.EndContractBlock(); 
>>
>>            return ReplaceInternal(oldValue, newValue); 
>>        } 
>>
>>
>>Bummer - it calls ReplaceInternal()
>>
>>private extern String ReplaceInternal(String oldValue, String newValue);
>>
>>
>>
>>Some comments in String.cs
>>
>>/*============================================================
>>** 
>>** Class:  String 
>>**
>>** 
>>** Purpose: Your favorite String class.  Native methods
>>** are implemented in StringNative.cpp
>>**
>>** 
>>===========================================================*/
>>>
>>
>>
>>Have not been able to find StringNative.cpp but I expect it won't create a C# char[] object
>
>Dunno. Does StringBuilder.Replace() also delegate to StringNative ?

From what I gather
StringBuilder uses a char[] and a linked list of blocks ( a block is another StringBuilder), each StringBuilder has a pointer to the previous StringBuilder (block)
Each StringBuilder holds a block or char[] of max 8000 chars. The aim is to keep the arrays out of the large object heap

You only see the StringBuilder you have created, but there may be more than one..

( lots of code marked Unsafe in there )




It uses two externs
 internal unsafe extern void ReplaceBufferInternal(char* newBuffer, int newLength);
 internal unsafe extern void ReplaceBufferAnsiInternal(sbyte* newBuffer, int newLength); 
As to copying, it has a method
 unsafe private static void ThreadSafeCopy(char* sourcePtr, char[] destination, int destinationIndex, int count)
which calls String.wstrcpy() which uses pointers
 internal static unsafe void wstrcpy(char *dmem, char *smem, int charCount)
Anyway - download the source and enjoy browsing
Gregory
Previous
Reply
Map
View

Click here to load this message in the networking platform