.NETGURU
Some info that preceeded the benchmark test....
Messages   Related Types
This message was discovered on ASPFriends.com 'aspngspeed' list.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.

Charles M. Carroll (VIP)
****************************************
I posted the following to Dan Wahlin:

One thing I am curious about Dan is why your ASP.net examples on your site=
=20
and book are so extremely mired in response.writes?

sub page_load(s as object, e as eventargs)
for counter=3D1 TO 100
response.write (i & "<br>")
next
end sub

correct:
sub page_load(s as object, e as eventargs)
dim sb as new stringbuilder
for counter=3D1 TO 100
sb.append (i)
sb.append ("<br>")
next
target1.text=3Dsb.tostring()
end sub

<asp:literal id=3D"target1" runat=3D"server"/>

The second approach the graphic designer can move around the target1 tag to=
=20
decide where the LOOP output goes. Also it has a proper "control tree" in=20
second example whereas the first one does not.

I was just curious why your site and books are still emphasizing=20
response.write ? Don't get me wrong you are not the only one -- I have=20
20-30 books that still do that but your XML examples are so cutting edge=20
and perfect that this makes them seem less perfect.

****************************************************
Dan replied:

Now you didn=92t actually think I coded perfect examples did you? :)

Actually, I generally prefer the StringBuilder class more now because as=20
you mention you have more control over where the output actually goes which=
=20
comes in handy when you want to update the property of a server=20
control. To be honest the samples probably should have relied more on=20
using a label control (and StringBuilder) as you demonstrated since server=
=20
controls offer so many advantages especially when labor is divided among=20
HTML programmers and .NET language programmers.

Many of the samples simply demonstrate using the XML classes and the output=
=20
is really only there so that there=92s some visual feedback for the=20
reader. A lot of using XML doesn=92t really involve any output necessarily=
=20
to the browser (that=92s of course a very general statement) so using=20
Response.Write isn=92t really bad in these cases IMHO. For example, one of=
=20
the samples in the book shows how to walk through an XML document using the=
=20
XmlTextReader. It basically re-displays the document in the browser as it=
=20
is parsed. Although this one sample is good for seeing how to use this=20
class, it=92s not something you=92re likely to do for =93real=94 in an=
application=20
so myStringbuilder.Append() really offers no advantage over=
Response.Write().

You got me wondering about performance though so I ran a few tests to see=20
how things panned out. From a performance perspective Response.Write=20
statements are much faster than concatenating strings (as we all knew), and=
=20
are very similar to using the StringBuilder in cases where you=92re simply=
=20
writing out strings to the browser Response stream. Granted, the test can=
=20
be tweaked to give different results I realize. Run the following (add the=
=20
Trace=3D=94true=94 directive into the ASP.NET page or enable tracing in=20
web.config) and scroll down to the Trace section:

private void Page_Load(object sender, System.EventArgs e) {

Trace.Write("Response.Write","");

for (int i=3D0;i<10000;i++) {

Response.Write("This is a test");

}

Trace.Write("Response.Write","");

Trace.Write("StringBuilder","");

StringBuilder sb =3D new StringBuilder();

for (int i=3D0;i<10000;i++) {

sb.Append("This is a test");

}

Response.Write(sb.ToString());

Trace.Write("StringBuilder","");

Trace.Write("Concat","");

string concat =3D String.Empty;

for (int i=3D0;i<10000;i++) {

concat +=3D "This is a test";

}

Response.Write(concat);

Trace.Write("Concat","");

}

You=92ll hopefully see similar results that I see (hit refresh a few times=
to=20
get a better average)=85basically that Response.Write is as good and=20
sometimes better speed-wise than using the StringBuilder and both of those=
=20
are much, much, much better than using string concatenation.

Now, I definitely agree with you that more perfect examples would leverage=
=20
some of the server controls more to display the output simply because you=20
can now in ASP.NET and it=92s a =93cleaner=94 solution. But I=92d argue=
that it=20
really depends on if the app needs to use them or not and many of the=20
samples really don=92t need server controls=85.they=92re simply=
demonstrating how=20
to work with XML classes and creating some visual output to show what the=20
classes are doing behind the scenes since in many cases you really wouldn=92=
t=20
have any visual output (parsing XML and updating a db for instance).

There=92s always ways I can improve things (just ask my wife) so thanks=
for=20
asking me about this. I=92ll try to be less Response.Write oriented in the=
=20
future when the samples generate some visual output for the reader. J

Dan

Reply to this message...
 
    
Sterling Bates (VIP)
Perhaps if we had more technical details on the StringBuilder class we could
make more refined use of it. For instance, if the StringBuilder class hides
an array of strings (built from .Append() calls, as opposed to concatenating
on every .Append() call), then perhaps even more overhead can be saved by
implementing a StringBuilder.SendToResponse() method. The logic:

Currently it's only the process of building the string (multiple
concatenations) that cause any drag. Assuming that all of the strings are
stored in the array, then calling the .ToString() method eliminates this
benefit (or at least decreases it). However, if the Response.Write method
call is "just as fast", or even similar in speed, then perhaps a developer
can instruct the StringBuilder class to Response.Write all of the strings
in the array out, rather than concatenating them all. That way they're
streamed, there's no memory reallocation (albeit at the stream level, but
that's a given), and you save any cost of assembling a string.

What do you think?

Of course, if it does concatenation on every .Append() call, I don't know
where we're getting any benefit out (unless this is a VB issue dragging it's
way through every version...).

-----Original Message-----
From: Charles M. Carroll [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 5:54 PM
To: aspngspeed
Subject: [aspngspeed] Some info that preceeded the benchmark test....

****************************************
I posted the following to Dan Wahlin:

One thing I am curious about Dan is why your ASP.net examples on your site
and book are so extremely mired in response.writes?

sub page_load(s as object, e as eventargs)
for counter=1 TO 100
response.write (i & "<br>")
next
end sub

correct:
sub page_load(s as object, e as eventargs)
dim sb as new stringbuilder
for counter=1 TO 100
sb.append (i)
sb.append ("<br>")
next
target1.text=sb.tostring()
end sub

<asp:literal id="target1" runat="server"/>

The second approach the graphic designer can move around the target1 tag to
decide where the LOOP output goes. Also it has a proper "control tree" in
second example whereas the first one does not.

I was just curious why your site and books are still emphasizing
response.write ? Don't get me wrong you are not the only one -- I have
20-30 books that still do that but your XML examples are so cutting edge
and perfect that this makes them seem less perfect.

****************************************************
Dan replied:

Now you didn't actually think I coded perfect examples did you? :)

Actually, I generally prefer the StringBuilder class more now because as
you mention you have more control over where the output actually goes which
comes in handy when you want to update the property of a server
control. To be honest the samples probably should have relied more on
using a label control (and StringBuilder) as you demonstrated since server
controls offer so many advantages especially when labor is divided among
HTML programmers and .NET language programmers.

Many of the samples simply demonstrate using the XML classes and the output
is really only there so that there's some visual feedback for the
reader. A lot of using XML doesn't really involve any output necessarily
to the browser (that's of course a very general statement) so using
Response.Write isn't really bad in these cases IMHO. For example, one of
the samples in the book shows how to walk through an XML document using the
XmlTextReader. It basically re-displays the document in the browser as it
is parsed. Although this one sample is good for seeing how to use this
class, it's not something you're likely to do for "real" in an application
so myStringbuilder.Append() really offers no advantage over
Response.Write().

You got me wondering about performance though so I ran a few tests to see
how things panned out. From a performance perspective Response.Write
statements are much faster than concatenating strings (as we all knew), and
are very similar to using the StringBuilder in cases where you're simply
writing out strings to the browser Response stream. Granted, the test can
be tweaked to give different results I realize. Run the following (add the
Trace="true" directive into the ASP.NET page or enable tracing in
web.config) and scroll down to the Trace section:

private void Page_Load(object sender, System.EventArgs e) {

Trace.Write("Response.Write","");

for (int i=0;i<10000;i++) {

Response.Write("This is a test");

}

Trace.Write("Response.Write","");

Trace.Write("StringBuilder","");

StringBuilder sb = new StringBuilder();

for (int i=0;i<10000;i++) {

sb.Append("This is a test");

}

Response.Write(sb.ToString());

Trace.Write("StringBuilder","");

Trace.Write("Concat","");

string concat = String.Empty;

for (int i=0;i<10000;i++) {

concat += "This is a test";

}

Response.Write(concat);

Trace.Write("Concat","");

}

You'll hopefully see similar results that I see (hit refresh a few times to
get a better average)...basically that Response.Write is as good and
sometimes better speed-wise than using the StringBuilder and both of those
are much, much, much better than using string concatenation.

Now, I definitely agree with you that more perfect examples would leverage
some of the server controls more to display the output simply because you
can now in ASP.NET and it's a "cleaner" solution. But I'd argue that it
really depends on if the app needs to use them or not and many of the
samples really don't need server controls....they're simply demonstrating
how
to work with XML classes and creating some visual output to show what the
classes are doing behind the scenes since in many cases you really wouldn't
have any visual output (parsing XML and updating a db for instance).

There's always ways I can improve things (just ask my wife) so thanks for
asking me about this. I'll try to be less Response.Write oriented in the
future when the samples generate some visual output for the reader. J

Dan

| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives
Reply to this message...
 
    
Dan Wahlin
Yeah, more information on what occurs behind the scenes is always a good
thing. The IL for the StringBuilder Append() method looks like the
following for one of the string parameter overloads:

StringBuilder <urn:object:0> .Append <urn:object:1>

.maxstack 3
.locals (int <urn:object:2> V_0, string <urn:object:3> V_1)
L_0000: ldarg.1
L_0001: ldnull
L_0002: call string <urn:object:4> .op_Equality <urn:object:5>
L_0007: brfalse.s L_000b
L_0009: ldarg.0
L_000a: ret
L_000b: ldarg.0
L_000c: ldfld StringBuilder <urn:object:6> .m_StringValue <urn:object:7>

L_0011: callvirt string <urn:object:8> .get_Length <urn:object:9>
L_0016: ldarg.1
L_0017: callvirt string <urn:object:10> .get_Length <urn:object:11>
L_001c: add
L_001d: stloc.0
L_001e: ldarg.0
L_001f: ldloc.0
L_0020: call StringBuilder <urn:object:12> .NeedsAllocation
<urn:object:13>
L_0025: brfalse.s L_003f
L_0027: ldarg.0
L_0028: ldloc.0
L_0029: call StringBuilder <urn:object:14> .GetNewString <urn:object:15>

L_002e: stloc.1
L_002f: ldloc.1
L_0030: ldarg.1
L_0031: callvirt string <urn:object:16> .AppendInPlace <urn:object:17>
L_0036: ldarg.0
L_0037: ldloc.1
L_0038: call StringBuilder <urn:object:18> .ReplaceString
<urn:object:19>
L_003d: br.s L_004b
L_003f: ldarg.0
L_0040: ldfld StringBuilder <urn:object:20> .m_StringValue
<urn:object:21>
L_0045: ldarg.1
L_0046: callvirt string <urn:object:22> .AppendInPlace <urn:object:23>
L_004b: ldarg.0
L_004c: ret

Anyone an IL expert that can give more insight into this? The
interesting things I see there are AppendInPlace, ReplaceString,
NeedsAllocation, and GetNewString. Expanding GetNewString it has the
following call tree:

System.Environment.GetResourceString()
System.ArgumentOutOfRangeException
System.String.get_ArrayLength()
System.String.GetStringForStringBuilder() (which has the following calls
in it.)
System.String.FastAllocateString()
System.String.get_Length()
System.String.FillString()

NeedsAllocation has:

System.String.get_ArrayLength() in it also. Because of the speed it
gives and the presence of get_ArrayLength() in several places it would
seem that it's not doing any type of concatenation or else it wouldn't
perform so great. Someone with more expertise in this area care to
comment?

Dan

---------------------------------------------------------------------
Get focused ASP.NET/XML articles and code at
<http://www.XMLforASP.NET> http://www.XMLforASP.NET

<http://www.amazon.com/exec/obidos/ASIN/0672320398/ref=ase_xmlforaspnetd
-20/103-9498093-2544665> XML for ASP.NET Developers
by Dan Wahlin
In bookstores everywhere!
---------------------------------------------------------------------

-----Original Message-----
From: Sterling Bates [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 9:43 PM
To: aspngspeed
Subject: [aspngspeed] RE: Some info that preceeded the benchmark
test....

Perhaps if we had more technical details on the StringBuilder class we
could make more refined use of it. For instance, if the StringBuilder
class hides an array of strings (built from .Append() calls, as opposed
to concatenating on every .Append() call), then perhaps even more
overhead can be saved by implementing a StringBuilder.SendToResponse()
method. The logic:
Currently it's only the process of building the string (multiple
concatenations) that cause any drag. Assuming that all of the strings
are stored in the array, then calling the .ToString() method eliminates
this benefit (or at least decreases it). However, if the Response.Write
method call is "just as fast", or even similar in speed, then perhaps a
developer can instruct the StringBuilder class to Response.Write all of
the strings in the array out, rather than concatenating them all. That
way they're streamed, there's no memory reallocation (albeit at the
stream level, but that's a given), and you save any cost of assembling a
string.
What do you think?
Of course, if it does concatenation on every .Append() call, I don't
know where we're getting any benefit out (unless this is a VB issue
dragging it's way through every version...).
-----Original Message-----
From: Charles M. Carroll [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 5:54 PM
To: aspngspeed
Subject: [aspngspeed] Some info that preceeded the benchmark test....

****************************************
I posted the following to Dan Wahlin:
One thing I am curious about Dan is why your ASP.net examples on your
site
and book are so extremely mired in response.writes?
sub page_load(s as object, e as eventargs)
for counter=1 TO 100
response.write (i & "<br>")
next
end sub
correct:
sub page_load(s as object, e as eventargs)
dim sb as new stringbuilder
for counter=1 TO 100
sb.append (i)
sb.append ("<br>")
next
target1.text=sb.tostring()
end sub
<asp:literal id="target1" runat="server"/>
The second approach the graphic designer can move around the target1 tag
to
decide where the LOOP output goes. Also it has a proper "control tree"
in
second example whereas the first one does not.
I was just curious why your site and books are still emphasizing
response.write ? Don't get me wrong you are not the only one -- I have
20-30 books that still do that but your XML examples are so cutting edge

and perfect that this makes them seem less perfect.
****************************************************
Dan replied:
Now you didn't actually think I coded perfect examples did you? :)
Actually, I generally prefer the StringBuilder class more now because as

you mention you have more control over where the output actually goes
which
comes in handy when you want to update the property of a server
control. To be honest the samples probably should have relied more on
using a label control (and StringBuilder) as you demonstrated since
server
controls offer so many advantages especially when labor is divided among

HTML programmers and .NET language programmers.
Many of the samples simply demonstrate using the XML classes and the
output
is really only there so that there's some visual feedback for the
reader. A lot of using XML doesn't really involve any output
necessarily
to the browser (that's of course a very general statement) so using
Response.Write isn't really bad in these cases IMHO. For example, one
of
the samples in the book shows how to walk through an XML document using
the
XmlTextReader. It basically re-displays the document in the browser as
it
is parsed. Although this one sample is good for seeing how to use this
class, it's not something you're likely to do for "real" in an
application
so myStringbuilder.Append() really offers no advantage over
Response.Write().
You got me wondering about performance though so I ran a few tests to
see
how things panned out. From a performance perspective Response.Write
statements are much faster than concatenating strings (as we all knew),
and
are very similar to using the StringBuilder in cases where you're simply

writing out strings to the browser Response stream. Granted, the test
can
be tweaked to give different results I realize. Run the following (add
the
Trace="true" directive into the ASP.NET page or enable tracing in
web.config) and scroll down to the Trace section:
private void Page_Load(object sender, System.EventArgs e) {
Trace.Write("Response.Write","");
for (int i=0;i<10000;i++) {
Response.Write("This is a test");
}
Trace.Write("Response.Write","");
Trace.Write("StringBuilder","");
StringBuilder sb = new StringBuilder();
for (int i=0;i<10000;i++) {
sb.Append("This is a test");
}
Response.Write(sb.ToString());
Trace.Write("StringBuilder","");
Trace.Write("Concat","");
string concat = String.Empty;
for (int i=0;i<10000;i++) {
concat += "This is a test";
}
Response.Write(concat);
Trace.Write("Concat","");
}

You'll hopefully see similar results that I see (hit refresh a few times
to
get a better average)...basically that Response.Write is as good and
sometimes better speed-wise than using the StringBuilder and both of
those
are much, much, much better than using string concatenation.
Now, I definitely agree with you that more perfect examples would
leverage
some of the server controls more to display the output simply because
you
can now in ASP.NET and it's a "cleaner" solution. But I'd argue that it

really depends on if the app needs to use them or not and many of the
samples really don't need server controls....they're simply
demonstrating how
to work with XML classes and creating some visual output to show what
the
classes are doing behind the scenes since in many cases you really
wouldn't
have any visual output (parsing XML and updating a db for instance).
There's always ways I can improve things (just ask my wife) so thanks
for
asking me about this. I'll try to be less Response.Write oriented in
the
future when the samples generate some visual output for the reader. J
Dan

| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives
| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives
Reply to this message...
 
    
Joel Mueller
If it's anything like the stringbuilder-type objects I've seen for VB6,
it's got an internal character array that's 2-3 times the size of the
actual string that it contains. When you append something to the
stringbuilder, it can just copy those characters into the pre-allocated
array after the end of the set of characters that have already been
inserted. When the array fills up, it creates a new array twice as big
and copies the current array into it (the algorithm's probably more
sophisticated than that, but you get the idea). That way it only has to
reallocate memory infrequently, rather than with every single append.
When you call ToString(), it simply outputs the portion of the character
array that actually has data in it as a string.

If that's correct, then the Capacity property is probably the length of
the character array. If you knew that the string you were building was
going to be at least a certain number of characters, setting the initial
capacity to that value should help you avoid unnecessary reallocations
of the internal character array. On the other hand, setting the Capacity
too high would just waste memory.

- Joel
-----Original Message-----
From: Dan Wahlin [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 11:53 PM
To: aspngspeed
Subject: [aspngspeed] RE: Some info that preceeded the benchmark
test....

Yeah, more information on what occurs behind the scenes is always a good
thing. The IL for the StringBuilder Append() method looks like the
following for one of the string parameter overloads:

StringBuilder <urn:object:0> .Append <urn:object:1>

.maxstack 3
.locals (int <urn:object:2> V_0, string <urn:object:3> V_1)
L_0000: ldarg.1
L_0001: ldnull
L_0002: call string <urn:object:4> .op_Equality <urn:object:5>
L_0007: brfalse.s L_000b
L_0009: ldarg.0
L_000a: ret
L_000b: ldarg.0
L_000c: ldfld StringBuilder <urn:object:6> .m_StringValue <urn:object:7>

L_0011: callvirt string <urn:object:8> .get_Length <urn:object:9>
L_0016: ldarg.1
L_0017: callvirt string <urn:object:10> .get_Length <urn:object:11>
L_001c: add
L_001d: stloc.0
L_001e: ldarg.0
L_001f: ldloc.0
L_0020: call StringBuilder <urn:object:12> .NeedsAllocation
<urn:object:13>
L_0025: brfalse.s L_003f
L_0027: ldarg.0
L_0028: ldloc.0
L_0029: call StringBuilder <urn:object:14> .GetNewString <urn:object:15>

L_002e: stloc.1
L_002f: ldloc.1
L_0030: ldarg.1
L_0031: callvirt string <urn:object:16> .AppendInPlace <urn:object:17>
L_0036: ldarg.0
L_0037: ldloc.1
L_0038: call StringBuilder <urn:object:18> .ReplaceString
<urn:object:19>
L_003d: br.s L_004b
L_003f: ldarg.0
L_0040: ldfld StringBuilder <urn:object:20> .m_StringValue
<urn:object:21>
L_0045: ldarg.1
L_0046: callvirt string <urn:object:22> .AppendInPlace <urn:object:23>
L_004b: ldarg.0
L_004c: ret

Anyone an IL expert that can give more insight into this? The
interesting things I see there are AppendInPlace, ReplaceString,
NeedsAllocation, and GetNewString. Expanding GetNewString it has the
following call tree:

System.Environment.GetResourceString()
System.ArgumentOutOfRangeException
System.String.get_ArrayLength()
System.String.GetStringForStringBuilder() (which has the following calls
in it.)
System.String.FastAllocateString()
System.String.get_Length()
System.String.FillString()

NeedsAllocation has:

System.String.get_ArrayLength() in it also. Because of the speed it
gives and the presence of get_ArrayLength() in several places it would
seem that it's not doing any type of concatenation or else it wouldn't
perform so great. Someone with more expertise in this area care to
comment?

Dan

---------------------------------------------------------------------
Get focused ASP.NET/XML articles and code at
<http://www.XMLforASP.NET> http://www.XMLforASP.NET

<http://www.amazon.com/exec/obidos/ASIN/0672320398/ref=ase_xmlforaspnetd
-20/103-9498093-2544665> XML for ASP.NET Developers
by Dan Wahlin
In bookstores everywhere!
---------------------------------------------------------------------

-----Original Message-----
From: Sterling Bates [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 9:43 PM
To: aspngspeed
Subject: [aspngspeed] RE: Some info that preceeded the benchmark
test....

Perhaps if we had more technical details on the StringBuilder class we
could make more refined use of it. For instance, if the StringBuilder
class hides an array of strings (built from .Append() calls, as opposed
to concatenating on every .Append() call), then perhaps even more
overhead can be saved by implementing a StringBuilder.SendToResponse()
method. The logic:
Currently it's only the process of building the string (multiple
concatenations) that cause any drag. Assuming that all of the strings
are stored in the array, then calling the .ToString() method eliminates
this benefit (or at least decreases it). However, if the Response.Write
method call is "just as fast", or even similar in speed, then perhaps a
developer can instruct the StringBuilder class to Response.Write all of
the strings in the array out, rather than concatenating them all. That
way they're streamed, there's no memory reallocation (albeit at the
stream level, but that's a given), and you save any cost of assembling a
string.
What do you think?
Of course, if it does concatenation on every .Append() call, I don't
know where we're getting any benefit out (unless this is a VB issue
dragging it's way through every version...).
-----Original Message-----
From: Charles M. Carroll [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 5:54 PM
To: aspngspeed
Subject: [aspngspeed] Some info that preceeded the benchmark test....

****************************************
I posted the following to Dan Wahlin:
One thing I am curious about Dan is why your ASP.net examples on your
site
and book are so extremely mired in response.writes?
sub page_load(s as object, e as eventargs)
for counter=1 TO 100
response.write (i & "<br>")
next
end sub
correct:
sub page_load(s as object, e as eventargs)
dim sb as new stringbuilder
for counter=1 TO 100
sb.append (i)
sb.append ("<br>")
next
target1.text=sb.tostring()
end sub
<asp:literal id="target1" runat="server"/>
The second approach the graphic designer can move around the target1 tag
to
decide where the LOOP output goes. Also it has a proper "control tree"
in
second example whereas the first one does not.
I was just curious why your site and books are still emphasizing
response.write ? Don't get me wrong you are not the only one -- I have
20-30 books that still do that but your XML examples are so cutting edge

and perfect that this makes them seem less perfect.
****************************************************
Dan replied:
Now you didn't actually think I coded perfect examples did you? :)
Actually, I generally prefer the StringBuilder class more now because as

you mention you have more control over where the output actually goes
which
comes in handy when you want to update the property of a server
control. To be honest the samples probably should have relied more on
using a label control (and StringBuilder) as you demonstrated since
server
controls offer so many advantages especially when labor is divided among

HTML programmers and .NET language programmers.
Many of the samples simply demonstrate using the XML classes and the
output
is really only there so that there's some visual feedback for the
reader. A lot of using XML doesn't really involve any output
necessarily
to the browser (that's of course a very general statement) so using
Response.Write isn't really bad in these cases IMHO. For example, one
of
the samples in the book shows how to walk through an XML document using
the
XmlTextReader. It basically re-displays the document in the browser as
it
is parsed. Although this one sample is good for seeing how to use this
class, it's not something you're likely to do for "real" in an
application
so myStringbuilder.Append() really offers no advantage over
Response.Write().
You got me wondering about performance though so I ran a few tests to
see
how things panned out. From a performance perspective Response.Write
statements are much faster than concatenating strings (as we all knew),
and
are very similar to using the StringBuilder in cases where you're simply

writing out strings to the browser Response stream. Granted, the test
can
be tweaked to give different results I realize. Run the following (add
the
Trace="true" directive into the ASP.NET page or enable tracing in
web.config) and scroll down to the Trace section:
private void Page_Load(object sender, System.EventArgs e) {
Trace.Write("Response.Write","");
for (int i=0;i<10000;i++) {
Response.Write("This is a test");
}
Trace.Write("Response.Write","");
Trace.Write("StringBuilder","");
StringBuilder sb = new StringBuilder();
for (int i=0;i<10000;i++) {
sb.Append("This is a test");
}
Response.Write(sb.ToString());
Trace.Write("StringBuilder","");
Trace.Write("Concat","");
string concat = String.Empty;
for (int i=0;i<10000;i++) {
concat += "This is a test";
}
Response.Write(concat);
Trace.Write("Concat","");
}

You'll hopefully see similar results that I see (hit refresh a few times
to
get a better average)...basically that Response.Write is as good and
sometimes better speed-wise than using the StringBuilder and both of
those
are much, much, much better than using string concatenation.
Now, I definitely agree with you that more perfect examples would
leverage
some of the server controls more to display the output simply because
you
can now in ASP.NET and it's a "cleaner" solution. But I'd argue that it

really depends on if the app needs to use them or not and many of the
samples really don't need server controls....they're simply
demonstrating how
to work with XML classes and creating some visual output to show what
the
classes are doing behind the scenes since in many cases you really
wouldn't
have any visual output (parsing XML and updating a db for instance).
There's always ways I can improve things (just ask my wife) so thanks
for
asking me about this. I'll try to be less Response.Write oriented in
the
future when the samples generate some visual output for the reader. J
Dan

| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives
| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives

| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives
Reply to this message...
 
    
Joel Mueller
Here's one program's interpretation of that MSIL, assuming I'm looking
at the same overload that you are. It seems to be working with some
undocumented internal methods in the String object, such as
AppendInPlace, ArrayLength, and InternalCopy. Looking further, there's
even an internal method on the String object called "NullTerminate()"
(!).

public StringBuilder Append(string value)
{
string local0;
int local1;
int local2;
string local3;

if (value == null)
return this;
local0 = this.m_StringValue;
local1 = local0.Length;
local2 = local1 + value.Length;
if (this.NeedsAllocation(local0, local2))
{
local3 = this.GetNewString(local0, local2);
local3.AppendInPlace(value, local1);
this.ReplaceString(local3);
}
else
{
local0.AppendInPlace(value, local1);
this.m_StringValue = local0;
}
return this;
}

private string GetNewString(string currentString, int requiredLength)
{
int local0;

requiredLength = requiredLength + 1;
if (requiredLength > this.m_MaxCapacity)
throw new
ArgumentOutOfRangeException(System.Environment.GetResourceString("Argume
ntOutOfRange_NegativeCapacity"), "requiredLength");
local0 = currentString.Capacity * 2;
if (local0 < requiredLength)
local0 = requiredLength;
if (local0 > this.m_MaxCapacity)
local0 = this.m_MaxCapacity;
if (local0 <= 0)
throw new
ArgumentOutOfRangeException(System.Environment.GetResourceString("Argume
ntOutOfRange_NegativeCapacity"));
return System.String.GetStringForStringBuilder(currentString, local0);
}

private bool NeedsAllocation(string currentString, int requiredLength)
{
if (currentString.ArrayLength > requiredLength)
return this.m_COW == 0 == 0;
return 1;
}

...and for good measure...

public virtual string ToString()
{
if (2 * this.m_StringValue.Length < this.m_StringValue.ArrayLength)
return System.String.InternalCopy(this.m_StringValue);
this.m_COW = 1;
this.m_StringValue.ClearPostNullChar();
return this.m_StringValue;
}

-----Original Message-----
From: Dan Wahlin [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 11:53 PM
To: aspngspeed
Subject: [aspngspeed] RE: Some info that preceeded the benchmark
test....

Yeah, more information on what occurs behind the scenes is always a good
thing. The IL for the StringBuilder Append() method looks like the
following for one of the string parameter overloads:

StringBuilder <urn:object:0> .Append <urn:object:1>

.maxstack 3
.locals (int <urn:object:2> V_0, string <urn:object:3> V_1)
L_0000: ldarg.1
L_0001: ldnull
L_0002: call string <urn:object:4> .op_Equality <urn:object:5>
L_0007: brfalse.s L_000b
L_0009: ldarg.0
L_000a: ret
L_000b: ldarg.0
L_000c: ldfld StringBuilder <urn:object:6> .m_StringValue <urn:object:7>

L_0011: callvirt string <urn:object:8> .get_Length <urn:object:9>
L_0016: ldarg.1
L_0017: callvirt string <urn:object:10> .get_Length <urn:object:11>
L_001c: add
L_001d: stloc.0
L_001e: ldarg.0
L_001f: ldloc.0
L_0020: call StringBuilder <urn:object:12> .NeedsAllocation
<urn:object:13>
L_0025: brfalse.s L_003f
L_0027: ldarg.0
L_0028: ldloc.0
L_0029: call StringBuilder <urn:object:14> .GetNewString <urn:object:15>

L_002e: stloc.1
L_002f: ldloc.1
L_0030: ldarg.1
L_0031: callvirt string <urn:object:16> .AppendInPlace <urn:object:17>
L_0036: ldarg.0
L_0037: ldloc.1
L_0038: call StringBuilder <urn:object:18> .ReplaceString
<urn:object:19>
L_003d: br.s L_004b
L_003f: ldarg.0
L_0040: ldfld StringBuilder <urn:object:20> .m_StringValue
<urn:object:21>
L_0045: ldarg.1
L_0046: callvirt string <urn:object:22> .AppendInPlace <urn:object:23>
L_004b: ldarg.0
L_004c: ret

Anyone an IL expert that can give more insight into this? The
interesting things I see there are AppendInPlace, ReplaceString,
NeedsAllocation, and GetNewString. Expanding GetNewString it has the
following call tree:

System.Environment.GetResourceString()
System.ArgumentOutOfRangeException
System.String.get_ArrayLength()
System.String.GetStringForStringBuilder() (which has the following calls
in it.)
System.String.FastAllocateString()
System.String.get_Length()
System.String.FillString()

NeedsAllocation has:

System.String.get_ArrayLength() in it also. Because of the speed it
gives and the presence of get_ArrayLength() in several places it would
seem that it's not doing any type of concatenation or else it wouldn't
perform so great. Someone with more expertise in this area care to
comment?

Dan

---------------------------------------------------------------------
Get focused ASP.NET/XML articles and code at
<http://www.XMLforASP.NET> http://www.XMLforASP.NET

<http://www.amazon.com/exec/obidos/ASIN/0672320398/ref=ase_xmlforaspnetd
-20/103-9498093-2544665> XML for ASP.NET Developers
by Dan Wahlin
In bookstores everywhere!
---------------------------------------------------------------------

-----Original Message-----
From: Sterling Bates [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 9:43 PM
To: aspngspeed
Subject: [aspngspeed] RE: Some info that preceeded the benchmark
test....

Perhaps if we had more technical details on the StringBuilder class we
could make more refined use of it. For instance, if the StringBuilder
class hides an array of strings (built from .Append() calls, as opposed
to concatenating on every .Append() call), then perhaps even more
overhead can be saved by implementing a StringBuilder.SendToResponse()
method. The logic:
Currently it's only the process of building the string (multiple
concatenations) that cause any drag. Assuming that all of the strings
are stored in the array, then calling the .ToString() method eliminates
this benefit (or at least decreases it). However, if the Response.Write
method call is "just as fast", or even similar in speed, then perhaps a
developer can instruct the StringBuilder class to Response.Write all of
the strings in the array out, rather than concatenating them all. That
way they're streamed, there's no memory reallocation (albeit at the
stream level, but that's a given), and you save any cost of assembling a
string.
What do you think?
Of course, if it does concatenation on every .Append() call, I don't
know where we're getting any benefit out (unless this is a VB issue
dragging it's way through every version...).
-----Original Message-----
From: Charles M. Carroll [mailto:Click here to reveal e-mail address]
Sent: Sunday, January 06, 2002 5:54 PM
To: aspngspeed
Subject: [aspngspeed] Some info that preceeded the benchmark test....

****************************************
I posted the following to Dan Wahlin:
One thing I am curious about Dan is why your ASP.net examples on your
site
and book are so extremely mired in response.writes?
sub page_load(s as object, e as eventargs)
for counter=1 TO 100
response.write (i & "<br>")
next
end sub
correct:
sub page_load(s as object, e as eventargs)
dim sb as new stringbuilder
for counter=1 TO 100
sb.append (i)
sb.append ("<br>")
next
target1.text=sb.tostring()
end sub
<asp:literal id="target1" runat="server"/>
The second approach the graphic designer can move around the target1 tag
to
decide where the LOOP output goes. Also it has a proper "control tree"
in
second example whereas the first one does not.
I was just curious why your site and books are still emphasizing
response.write ? Don't get me wrong you are not the only one -- I have
20-30 books that still do that but your XML examples are so cutting edge

and perfect that this makes them seem less perfect.
****************************************************
Dan replied:
Now you didn't actually think I coded perfect examples did you? :)
Actually, I generally prefer the StringBuilder class more now because as

you mention you have more control over where the output actually goes
which
comes in handy when you want to update the property of a server
control. To be honest the samples probably should have relied more on
using a label control (and StringBuilder) as you demonstrated since
server
controls offer so many advantages especially when labor is divided among

HTML programmers and .NET language programmers.
Many of the samples simply demonstrate using the XML classes and the
output
is really only there so that there's some visual feedback for the
reader. A lot of using XML doesn't really involve any output
necessarily
to the browser (that's of course a very general statement) so using
Response.Write isn't really bad in these cases IMHO. For example, one
of
the samples in the book shows how to walk through an XML document using
the
XmlTextReader. It basically re-displays the document in the browser as
it
is parsed. Although this one sample is good for seeing how to use this
class, it's not something you're likely to do for "real" in an
application
so myStringbuilder.Append() really offers no advantage over
Response.Write().
You got me wondering about performance though so I ran a few tests to
see
how things panned out. From a performance perspective Response.Write
statements are much faster than concatenating strings (as we all knew),
and
are very similar to using the StringBuilder in cases where you're simply

writing out strings to the browser Response stream. Granted, the test
can
be tweaked to give different results I realize. Run the following (add
the
Trace="true" directive into the ASP.NET page or enable tracing in
web.config) and scroll down to the Trace section:
private void Page_Load(object sender, System.EventArgs e) {
Trace.Write("Response.Write","");
for (int i=0;i<10000;i++) {
Response.Write("This is a test");
}
Trace.Write("Response.Write","");
Trace.Write("StringBuilder","");
StringBuilder sb = new StringBuilder();
for (int i=0;i<10000;i++) {
sb.Append("This is a test");
}
Response.Write(sb.ToString());
Trace.Write("StringBuilder","");
Trace.Write("Concat","");
string concat = String.Empty;
for (int i=0;i<10000;i++) {
concat += "This is a test";
}
Response.Write(concat);
Trace.Write("Concat","");
}

You'll hopefully see similar results that I see (hit refresh a few times
to
get a better average)...basically that Response.Write is as good and
sometimes better speed-wise than using the StringBuilder and both of
those
are much, much, much better than using string concatenation.
Now, I definitely agree with you that more perfect examples would
leverage
some of the server controls more to display the output simply because
you
can now in ASP.NET and it's a "cleaner" solution. But I'd argue that it

really depends on if the app needs to use them or not and many of the
samples really don't need server controls....they're simply
demonstrating how
to work with XML classes and creating some visual output to show what
the
classes are doing behind the scenes since in many cases you really
wouldn't
have any visual output (parsing XML and updating a db for instance).
There's always ways I can improve things (just ask my wife) so thanks
for
asking me about this. I'll try to be less Response.Write oriented in
the
future when the samples generate some visual output for the reader. J
Dan

| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives
| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives

| [aspngspeed] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngspeed.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives
Reply to this message...
 
    
Dan Wahlin
That sounds right on and would explain why there is Capacity and
EnsureCapacity as well as get_ArrayLength() behind the scenes. Thanks
for sharing more details on it.

Dan

---------------------------------------------------------------------
Get focused ASP.NET/XML articles and code at
<http://www.XMLforASP.NET> http://www.XMLforASP.NET

<http://www.amazon.com/exec/obidos/ASIN/0672320398/ref=ase_xmlforaspnetd
-20/103-9498093-2544665> XML for ASP.NET Developers
by Dan Wahlin
In bookstores everywhere!
---------------------------------------------------------------------

-----Original Message-----
From: Joel Mueller [mailto:Click here to reveal e-mail address]
Sent: Monday, January 07, 2002 12:20 AM
To: aspngspeed
Subject: [aspngspeed] RE: Some info that preceeded the benchmark
test....

If it's anything like the stringbuilder-type objects I've seen for VB6,
it's got an internal character array that's 2-3 times the size of the
actual string that it contains. When you append something to the
stringbuilder, it can just copy those characters into the pre-allocated
array after the end of the set of characters that have already been
inserted. When the array fills up, it creates a new array twice as big
and copies the current array into it (the algorithm's probably more
sophisticated than that, but you get the idea). That way it only has to
reallocate memory infrequently, rather than with every single append.
When you call ToString(), it simply outputs the portion of the character
array that actually has data in it as a string.

If that's correct, then the Capacity property is probably the length of
the character array. If you knew that the string you were building was
going to be at least a certain number of characters, setting the initial
capacity to that value should help you avoid unnecessary reallocations
of the internal character array. On the other hand, setting the Capacity
too high would just waste memory.

- Joel
Reply to this message...
 
 
System.ArgumentOutOfRangeException
System.Diagnostics.Trace
System.Environment
System.EventArgs
System.String
System.Text.StringBuilder
System.Xml.XmlTextReader




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification