By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,369 Members | 1,207 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,369 IT Pros & Developers. It's quick & easy.

StringBuilder and memory use

P: n/a
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.
Oct 26 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a
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 wrote:
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.
Oct 26 '06 #2

P: n/a
Arjan wrote:
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

Oct 26 '06 #3

P: n/a
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();
}
}

"Brian Gideon" <br*********@yahoo.comwrote in message
news:11**********************@b28g2000cwb.googlegr oups.com...
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 wrote:
>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.

Oct 26 '06 #4

P: n/a
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.

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:11*********************@k70g2000cwa.googlegro ups.com...
Arjan wrote:
>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

Oct 26 '06 #5

P: n/a
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

Arjan wrote:
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();
}
}
Oct 26 '06 #6

P: n/a
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/product...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;
}
}

"Brian Gideon" <br*********@yahoo.comwrote in message
news:11**********************@b28g2000cwb.googlegr oups.com...
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

Arjan wrote:
>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();
}
}

Oct 26 '06 #7

P: n/a
Arjan wrote:
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

Oct 26 '06 #8

P: n/a
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

Arjan wrote:
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/product...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;
}
}
Oct 26 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.