473,326 Members | 2,126 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

StringBuilder and memory use

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
8 2891
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

37
by: Kevin C | last post by:
Quick Question: StringBuilder is obviously more efficient dealing with string concatenations than the old '+=' method... however, in dealing with relatively large string concatenations (ie,...
3
by: Salvador | last post by:
Hi, I am using an old Win32 DLL that expects a LPBYTE as a parameter. The Stringbuilder appears to be working, the problem is that the component is sending me a string with NULL characters in the...
9
by: Peter Row | last post by:
Hi, I know this has been asked before, but reading the threads it is still not entirely clear. Deciding which .Replace( ) to use when. Typically if I create a string in a loop I always use a...
15
by: DV | last post by:
I have a StringBuilder that has a string with 12,000,000 characters. When I do a ToString(), I expect to have ~25,000,000 bytes worth of memory, yet, I end up with ~43,000,000 bytes. That's...
12
by: Richard Lewis Haggard | last post by:
I thought that the whole point of StringBuilder was that it was supposed to be a faster way of building strings than string. However, I just put together a simple little application to do a...
7
by: Arnd Iffland | last post by:
Hi, i want to use a StringBuilder to create a large string. After instatiation, the MaxCapacity is 2.147.483.647, what is large enough for my purpose. During my procedure i get a...
26
by: Hardy Wang | last post by:
Hi all, I know it is better to handle large string with a StringBuilder, but how does StringBuilder class improve the performance in the background? Thanks! -- WWW:...
5
by: =?Utf-8?B?SGFycnkgVg==?= | last post by:
I'm using a StringBuilder to build a SelectCommand string that returns a number of records. If that number is >0, I want to fill an arraylist with fields from the records for a listbox. Is it...
13
by: Tony Johansson | last post by:
Hello! I read in a book and here is a question and the answer that I'm not satisfied with. When should you use the StringBuilder class instead of the String class. 1.When building a string from...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.