StringBuilder and memory use

  • Thread starter Thread starter Arjan
  • Start date Start date
A

Arjan

Hello,

I have been looking for a couple of days now, but I can't find anything
about how to deal with StringBuilder and releasing the memory used by it.
When I use stringbuilder, the memory doesn't get released (or actually it
looks like that) and thus the used memory keeps growing. Is there a solution
to this?

Regards,
Arjan.
 
Arjan,

The only thing you need to do is stop referencing the object and it
will eventually collected by the GC. What makes you think the memory
isn't being released?

Brian
 
Arjan said:
I have been looking for a couple of days now, but I can't find anything
about how to deal with StringBuilder and releasing the memory used by it.
When I use stringbuilder, the memory doesn't get released (or actually it
looks like that) and thus the used memory keeps growing. Is there a solution
to this?

Chances are you're using Task Manager to look at memory usage - that's
not a good way of judging how much memory is in use, for various
reasons. (A Google search should help you on that front.)

My normal use for a StringBuilder is to create it, manipulate it,
convert it to a string and then let it fall out of scope. If that's how
you're using them, you should be fine.

Jon
 
Brian,
I used a memory profiler and everytime the app has to create a new
Stringbuilder the old one remains in the memory leaving the size of 2Mb
unchanged. I called the GC, but still nothing happens. I am sure that the
declared variable is only within the function. I even tried to set the
variable to null, but then the app creates an error. Below you can find the
code that I am using. It might not be the best ever written code. It is just
created to have a quick solution to generate time for a much better one.
Maybe someone of you can help me to figure out what is going wrong.
TIA,
Arjan.

private static string jmsSBuilder(string data, string idTag, int iSeqNr)
{
DateTime setTime = DateTime.Now;
StringBuilder buffer = new StringBuilder();
string sTime = setTime.Year.ToString() + "-" + setTime.Month.ToString() +
"-" + setTime.Day.ToString();
sTime += "T" + setTime.Hour.ToString() + ":" + setTime.Minute.ToString() +
":" + setTime.Second.ToString();
buffer.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
buffer.Append("<informa xmlns=\"http://www.informa.com/inf.xsd\">");
buffer.Append("<header>");
buffer.Append("<version>1.0</version>");
buffer.Append("<messageid>");
buffer.Append(iSeqNr.ToString());
buffer.Append("codamid");
buffer.Append(idTag);
buffer.Append("</messageid>");
buffer.Append("<correlationid>");
buffer.Append(iSeqNr.ToString());
buffer.Append("codacid");
buffer.Append(idTag);
buffer.Append("</correlationid>");
buffer.Append("<timestamp>");
buffer.Append(sTime);
buffer.Append("</timestamp>");
buffer.Append("<messagetype>");
buffer.Append(esbMessageType);
buffer.Append("</messagetype>");
buffer.Append("<environment>");
buffer.Append(esbEnvironment);
buffer.Append("</environment>");
buffer.Append("<topic>");
buffer.Append(esbTopic);
buffer.Append("</topic>");
buffer.Append("<dbaction>");
buffer.Append(esbDBAction);
buffer.Append("</dbaction>");
buffer.Append("<informa_company>");
buffer.Append(esbCompany);
buffer.Append("</informa_company>");
buffer.Append("<procedure>");
buffer.Append(esbProcedureName);
buffer.Append("</procedure>");
buffer.Append("</header>");
buffer.Append("<body>");
buffer.Append(data);
buffer.Append("</body>");
buffer.Append("</informa>");
string sMain = buffer.ToString();
buffer.Remove(0, buffer.Length);
return sMain;
}

private static void DataProcessing(string sConn, string sSQL)
{
string sGuid = Guid.NewGuid().ToString();
int MaxLength = esbMaxMessageSize * 1024;
int SeqNr = 0;
string jmsMessage = string.Empty;
int hdLength = jmsSBuilder(string.Empty, sGuid, SeqNr).Length;
bool audit = false;
StringBuilder info = new StringBuilder();
StringBuilder rij = new StringBuilder();
SqlConnection cn = new SqlConnection(sConn);
SqlCommand rs = new SqlCommand();
SqlDataReader dr = null;
try
{
cn.Open();
rs.Connection = cn;
rs.CommandText = sSQL;
dr = rs.ExecuteReader();
while (dr.Read())
{
rij.Append("<row>");
for (int i = 0; i < dr.FieldCount; i++)
{
rij.Append("<");
rij.Append(dr.GetName(i));
rij.Append(">");
rij.Append(Convert.ToString(dr.GetValue(i)));
rij.Append("</");
rij.Append(dr.GetName(i));
rij.Append(">");
}
rij.Append("</row>");
if ((info.Length + hdLength + rij.Length) < MaxLength)
{
info.Append(rij.ToString());
}
else
{
jmsMessage = jmsSBuilder(info.ToString(), sGuid, SeqNr);
audit = SonicMQ(jmsMessage);
SendAudit(audit);
info.Remove(0, info.Length);
info.Append(rij.ToString());
SeqNr++;
}
rij.Remove(0, rij.Length);
}
if (info.Length != 0)
{
jmsMessage = jmsSBuilder(info.ToString(), sGuid, SeqNr);
audit = SonicMQ(jmsMessage);
SendAudit(audit);
info.Remove(0, info.Length);
}
}
catch (Exception err)
{
SendEventLog("DataProcessing" + ": " + err.Message,
EventLogEntryType.Error);
}
finally
{
if (!dr.IsClosed)
dr.Close();
if (cn != null)
cn.Close();
}
}
 
Hi Jon,

Well, I am using it the way you explained. At least that's what I think. And
yes, I used Task Manager for a quick look at what is happening. Can you
recommend me a tool that does the job well to see what is happening?

Regards,

Arjan.
 
Arjan,

What error do you get when you set the variable to null. If it's a
NullReferenceException then you're using the reference after it has
been set to null.

I looked at the code and I noticed that you're passing a StringBuilder
object into the SonicMQ method. What is that method doing? If it's
somehow saving a reference to the object then that's your problem.

Brian
 
Brian,

The error I get is: Object reference not set to an instance of an object. I
have googled on stringbuilder, but there is nothing like a destructor for
stringbuilder and no one mentions to set it to null. So I am not sure if
this is good practice anyway.

SonicMQ is just a function that passes the string value to an SOA system
(Sonic ESB: http://www.sonicsoftware.com/products/sonic_esb/index.ssp). The
procedure that goes with it is below. I didn't send it in the previous
message, because I am using proprietary libraries and is most likely not
clearing up a lot.

Regards,
Arjan.

private static bool SonicMQ(string dbMessage)
{
try
{
Sonic.Jms.Connection connect = null;
Sonic.Jms.Session sendSession = null;
Sonic.Jms.MessageProducer sender = null;
Sonic.Jms.ConnectionFactory factory;
factory = (new Sonic.Jms.Cf.Impl.ConnectionFactory("tcp://"
+ esbServer + ":" + esbPort));
connect = factory.createConnection(esbUser, esbPassword);
sendSession = connect.createSession(false,
Sonic.Jms.SessionMode.AUTO_ACKNOWLEDGE);
Sonic.Jms.Queue sendQueue =
sendSession.createQueue(esbQueueName);
sender = sendSession.createProducer(sendQueue);
connect.start();
Sonic.Jms.TextMessage msg = sendSession.createTextMessage();
msg.setText(dbMessage);
sender.send(msg);
msg.clearBody();
msg = null;
if (sender != null)
{
sender.close();
sender = null;
}
if (sendSession != null)
{
sendSession.close();
sendSession = null;
}
if (connect != null)
{
connect.close();
connect = null;
}
factory = null;
dbMessage = null;
return true;
}
catch (Sonic.Jms.JMSException jmse)
{
SendEventLog(jmse.Message, EventLogEntryType.Error);
return false;
}
}
 
Arjan said:
Well, I am using it the way you explained. At least that's what I think. And
yes, I used Task Manager for a quick look at what is happening. Can you
recommend me a tool that does the job well to see what is happening?

As I suggested, Google is your friend. The top result of
http://www.google.com/search?q=task+manager+.net+memory
gives a good explanation of what's going on, and explains what to do
instead.

Jon
 
Arjan,

I apologize. I obviously didn't look close enough. SonicMQ accepts a
string and not a StringBuilder.

Yep, you're getting a NullReferenceException. That's pretty easy to
fix. Just figure out where you're setting the variable to null and
when it's next used. I would say it's generally not good practice to
set the variable to null.

Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top