473,761 Members | 2,440 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Fast string operations

I've been perf testing an application of mine and I've noticed that there
are a lot (and I mean A LOT -- megabytes and megabytes of 'em) System.String
instances being created.

I've done some analysis and I'm led to believe (but can't yet quantitatively
establish as fact) that the two basic culprits are a lot of calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a bunch
of strings faster than the GC can collect them, or perhaps there's some
weird interning/caching thing going on. Regardless, the number of string
instances grows and grows. It gets bumped down occasionally, but it's
basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( ) which
can perform in-place case-insensitive comparisons without generating new
string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the length
of a string, minus whitespace and without generating a new string instance,
in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what MSFT
did for all their string handling stuff inside System.String and using the
COMString stuff), but I'd like to try to avoid that, or at least use a
library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers
Nov 17 '05 #1
17 4666
Chad,

For the first scenario, your solution should give you an increase.

For the second scenario, you should use reflection once to get a
reference to the internal static character array WhitespaceChars on the
string class. Then, you can write a method which will cycle through a
string passed to it, like so:

public static bool TrimIsNullOrEmp ty(string value)
{
// If null, then get out.
if (value == null)
{
// Return true.
return true;
}

// Cycle through the characters in the string. If the character is not
found
// in the whitespace array, return false, otherwise, when done, return
true.
foreach (char c in value)
{
// If the character is not found in the WhitespaceArray , then return
// false.
if (Array.IndexOf< char>(Whitespac eArray, char) == -1)
{
// Return false.
return false;
}
}

// Return true, the string is full of whitespace.
return true;
}

I used the generic version of the IndexOf method on the Array class in
order to eliminate boxing. Also, if you really want to squeeze out every
last bit of performance from this, you can take the WhitespaceArray and use
the characters as keys in a dictionary. The number of whitespace characters
is 25 (right now, that is). However, if your strings typically are padded
with spaces, then you could get a big speed boost by copying the array
initially, and then placing the space character as the first element in the
array (which would cause most of the calls to IndexOf to return very
quickly, probably quicker than a lookup in a dictionary).

I am curious though, are you seeing a performance issue, or do you just
see the numbers and are worried about them? ASP.NET applications tend to
get in a nice groove with the GC over time.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:2r******** **********@torn ado.texas.rr.co m...
I've been perf testing an application of mine and I've noticed that there
are a lot (and I mean A LOT -- megabytes and megabytes of 'em)
System.String instances being created.

I've done some analysis and I'm led to believe (but can't yet
quantitatively establish as fact) that the two basic culprits are a lot of
calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a bunch
of strings faster than the GC can collect them, or perhaps there's some
weird interning/caching thing going on. Regardless, the number of string
instances grows and grows. It gets bumped down occasionally, but it's
basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( )
which can perform in-place case-insensitive comparisons without generating
new string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the
length of a string, minus whitespace and without generating a new string
instance, in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what
MSFT did for all their string handling stuff inside System.String and
using the COMString stuff), but I'd like to try to avoid that, or at least
use a library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers

Nov 17 '05 #2
> 1.) if( someString.ToLo wer() == "somestring " )

FxCop will actually catch and report instances of this for you. It is my 2nd
favorite tool outside of Visual Studio.
2.) if( someString != null && someString.Trim ().Length > 0 )
I would recommend using

if (someString != null)
someString = someString.Trim ();
else
someString = "";

if( someString.Leng th > 0 )

My assumption here is that you already intend to trim the string before it
is used.

--
Jonathan Allen
"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:2r******** **********@torn ado.texas.rr.co m... I've been perf testing an application of mine and I've noticed that there
are a lot (and I mean A LOT -- megabytes and megabytes of 'em)
System.String instances being created.

I've done some analysis and I'm led to believe (but can't yet
quantitatively establish as fact) that the two basic culprits are a lot of
calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a bunch
of strings faster than the GC can collect them, or perhaps there's some
weird interning/caching thing going on. Regardless, the number of string
instances grows and grows. It gets bumped down occasionally, but it's
basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( )
which can perform in-place case-insensitive comparisons without generating
new string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the
length of a string, minus whitespace and without generating a new string
instance, in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what
MSFT did for all their string handling stuff inside System.String and
using the COMString stuff), but I'd like to try to avoid that, or at least
use a library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers

Nov 17 '05 #3
Nicholas,

Thanks for the quick reply. Unfortunately I'm not using .NET 2.0 (yet!), so
I can't use Generics.

Would looping over chars like that slow things down significantly? Also, is
the char[] for each string cached with the string, or is a new one created
when you call things like ToCharArray() or foreach() on the string (not
every loop iteration, but on the first iteration)? Wouldn't I just be
replacing a new string instance with a new char[] and not get any net gain
over just calling .Trim()?

In your opinion, if I weren't against unsafe code, could I make this
significantly faster, or would it not afford me much difference?

As far as performance, on some of our clients' instances, memory growth is
rapid. It seems the more memory they have, the faster it grows which leads
me to believe that the GC is being lax since it has so much free memory and
doesn't see the need to aggressively collect memory. But it bothers our
clients and they perceive this to be a memory leak.

I realize it's an education issue, but I want to make sure that I'm
educating them correctly, as opposed to just making up a B.S. excuse and
Jedi hand-waving about the GC stuff.

Also, it's not an ASP.NET application, it's an ASP app that used to call
into VB6 COM objects. We've replaced the VB6 objects with .NET objects
exposing a "compatibil ity layer" that has a ComVisible API that is identical
(though not binary compatible) with the old VB6 stuff. Late-bound clients
don't know the difference other than a different ProgID for the COM objects.

So we're dealing with the wkst GC, as far as I know (since only ASP.NET uses
svr unless you host the CLR yourself, from what I understand). I'm not sure
how I'd even do that in an ASP/COM-interop situation, but, assuming it's
possible, would writing our own CLR host to use the svr GC help matters at
all?

Most of our clients' servers are dual-or-more processor boxes.

Thanks again,
Chad Myers

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote in
message news:Oz******** *****@TK2MSFTNG P15.phx.gbl...
Chad,

For the first scenario, your solution should give you an increase.

For the second scenario, you should use reflection once to get a
reference to the internal static character array WhitespaceChars on the
string class. Then, you can write a method which will cycle through a
string passed to it, like so:

public static bool TrimIsNullOrEmp ty(string value)
{
// If null, then get out.
if (value == null)
{
// Return true.
return true;
}

// Cycle through the characters in the string. If the character is not
found
// in the whitespace array, return false, otherwise, when done, return
true.
foreach (char c in value)
{
// If the character is not found in the WhitespaceArray , then
return
// false.
if (Array.IndexOf< char>(Whitespac eArray, char) == -1)
{
// Return false.
return false;
}
}

// Return true, the string is full of whitespace.
return true;
}

I used the generic version of the IndexOf method on the Array class in
order to eliminate boxing. Also, if you really want to squeeze out every
last bit of performance from this, you can take the WhitespaceArray and
use the characters as keys in a dictionary. The number of whitespace
characters is 25 (right now, that is). However, if your strings typically
are padded with spaces, then you could get a big speed boost by copying
the array initially, and then placing the space character as the first
element in the array (which would cause most of the calls to IndexOf to
return very quickly, probably quicker than a lookup in a dictionary).

I am curious though, are you seeing a performance issue, or do you just
see the numbers and are worried about them? ASP.NET applications tend to
get in a nice groove with the GC over time.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:2r******** **********@torn ado.texas.rr.co m...
I've been perf testing an application of mine and I've noticed that there
are a lot (and I mean A LOT -- megabytes and megabytes of 'em)
System.String instances being created.

I've done some analysis and I'm led to believe (but can't yet
quantitatively establish as fact) that the two basic culprits are a lot
of calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a
bunch of strings faster than the GC can collect them, or perhaps there's
some weird interning/caching thing going on. Regardless, the number of
string instances grows and grows. It gets bumped down occasionally, but
it's basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( )
which can perform in-place case-insensitive comparisons without
generating new string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the
length of a string, minus whitespace and without generating a new string
instance, in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what
MSFT did for all their string handling stuff inside System.String and
using the COMString stuff), but I'd like to try to avoid that, or at
least use a library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers


Nov 17 '05 #4
Jonathon:

Thanks for your quick response.

Unfortunately, in (2), we're not doing that. In most cases, it's OK to have
padded strings, just not all-whitespace strings.

Regardless, even with your suggestion, the .Trim() still creates a new
string instance and fills the heap with crap :(

Thanks again,
Chad

"Jonathan Allen" <x@x.x> wrote in message
news:eX******** ******@TK2MSFTN GP10.phx.gbl...
1.) if( someString.ToLo wer() == "somestring " )


FxCop will actually catch and report instances of this for you. It is my
2nd favorite tool outside of Visual Studio.
2.) if( someString != null && someString.Trim ().Length > 0 )


I would recommend using

if (someString != null)
someString = someString.Trim ();
else
someString = "";

if( someString.Leng th > 0 )

My assumption here is that you already intend to trim the string before it
is used.

--
Jonathan Allen
"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:2r******** **********@torn ado.texas.rr.co m...
I've been perf testing an application of mine and I've noticed that there
are a lot (and I mean A LOT -- megabytes and megabytes of 'em)
System.String instances being created.

I've done some analysis and I'm led to believe (but can't yet
quantitatively establish as fact) that the two basic culprits are a lot
of calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a
bunch of strings faster than the GC can collect them, or perhaps there's
some weird interning/caching thing going on. Regardless, the number of
string instances grows and grows. It gets bumped down occasionally, but
it's basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( )
which can perform in-place case-insensitive comparisons without
generating new string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the
length of a string, minus whitespace and without generating a new string
instance, in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what
MSFT did for all their string handling stuff inside System.String and
using the COMString stuff), but I'd like to try to avoid that, or at
least use a library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers


Nov 17 '05 #5
KH
For the second scenario -- trimming white space -- you could check the first
and last chars to see if they're whitespace and only perform the Trim() if
that condition is true:

string str = " lalala ";

if (Char.IsWhiteSp ace(str[0]) || Char.IsWhiteSpa ce(str[str.Length -1]))
{
str = str.Trim();
}
"Jonathan Allen" wrote:
1.) if( someString.ToLo wer() == "somestring " )


FxCop will actually catch and report instances of this for you. It is my 2nd
favorite tool outside of Visual Studio.
2.) if( someString != null && someString.Trim ().Length > 0 )


I would recommend using

if (someString != null)
someString = someString.Trim ();
else
someString = "";

if( someString.Leng th > 0 )

My assumption here is that you already intend to trim the string before it
is used.

--
Jonathan Allen
"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:2r******** **********@torn ado.texas.rr.co m...
I've been perf testing an application of mine and I've noticed that there
are a lot (and I mean A LOT -- megabytes and megabytes of 'em)
System.String instances being created.

I've done some analysis and I'm led to believe (but can't yet
quantitatively establish as fact) that the two basic culprits are a lot of
calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a bunch
of strings faster than the GC can collect them, or perhaps there's some
weird interning/caching thing going on. Regardless, the number of string
instances grows and grows. It gets bumped down occasionally, but it's
basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( )
which can perform in-place case-insensitive comparisons without generating
new string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the
length of a string, minus whitespace and without generating a new string
instance, in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what
MSFT did for all their string handling stuff inside System.String and
using the COMString stuff), but I'd like to try to avoid that, or at least
use a library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers


Nov 17 '05 #6
KH
Better yet (I didn't notice this overload before) ...

string str = " lalala ";

// Be sure to check that the string variable is not a null reference
// and its length is at least 1, otherwise you'll get index out of range
exceptions

if (Char.IsWhiteSp ace(str, 0) || Char.IsWhiteSpa ce(str, str.Length -1))
{
str = str.Trim();
}

"Jonathan Allen" wrote:
1.) if( someString.ToLo wer() == "somestring " )


FxCop will actually catch and report instances of this for you. It is my 2nd
favorite tool outside of Visual Studio.
2.) if( someString != null && someString.Trim ().Length > 0 )


I would recommend using

if (someString != null)
someString = someString.Trim ();
else
someString = "";

if( someString.Leng th > 0 )

My assumption here is that you already intend to trim the string before it
is used.

--
Jonathan Allen
"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:2r******** **********@torn ado.texas.rr.co m...
I've been perf testing an application of mine and I've noticed that there
are a lot (and I mean A LOT -- megabytes and megabytes of 'em)
System.String instances being created.

I've done some analysis and I'm led to believe (but can't yet
quantitatively establish as fact) that the two basic culprits are a lot of
calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a bunch
of strings faster than the GC can collect them, or perhaps there's some
weird interning/caching thing going on. Regardless, the number of string
instances grows and grows. It gets bumped down occasionally, but it's
basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( )
which can perform in-place case-insensitive comparisons without generating
new string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the
length of a string, minus whitespace and without generating a new string
instance, in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what
MSFT did for all their string handling stuff inside System.String and
using the COMString stuff), but I'd like to try to avoid that, or at least
use a library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers


Nov 17 '05 #7
KH,

Hrm, that's a good idea. In your first suggestion, I'm afraid of indexing
the char[] in the strings because I'm not sure when the char[] is created
(does it always tag along with the string, or is it only created the first
time you try to access the char[] -- through the indexer or through a call
to ToCharArray, etc).

But this suggestion just might work...

I'll look into it and let everyone know how it goes.

Thanks again everyone.

Sincerely,
Chad

"KH" <KH@discussions .microsoft.com> wrote in message
news:0F******** *************** ***********@mic rosoft.com...
Better yet (I didn't notice this overload before) ...

string str = " lalala ";

// Be sure to check that the string variable is not a null reference
// and its length is at least 1, otherwise you'll get index out of range
exceptions

if (Char.IsWhiteSp ace(str, 0) || Char.IsWhiteSpa ce(str, str.Length -1))
{
str = str.Trim();
}

Nov 17 '05 #8
Chad,

Looping over characters like that can't slow things down that much. No
matter what you do, you will have to perform some sort of loop operation to
check the string. There is no other way to do it.

Also, the char[] that is enumerated through is not created for every
iteration through the string. Rather, the string implements IEnumerable,
and then the IEnumerator implementation returned will return a new char for
each iteration.

I don't think that using unsafe code is going to make things any better,
only because it's going to do the same thing you are going to do, maybe with
one or two operations eliminated in between (and I mean IL operations, not
function calls).

When you call Trim, a loop is going to start from the beginning of the
string, counting the whitespace characters that are at the beginning. Then
it is going to perform another loop to scan the end of the stirng for
whitespace characters. Once that is done, it will get the substring, which
will have to loop through the characters to copy them into a new string (on
some level or another, a loop is going to execute).

Also, the original issue was the amount of memory that is being consumed
(which in reality, it is not, but it is a customer education issue). If the
performance of the application is suffering, it is not because of these
operations. I would look elsewhere. The fact that you are using COM
interop means that for every call you make across that boundary, you are
adding something on the order of 40 extra operations. Depending on how
chunky your calls are, this could be a factor.

In the end, the GC is going to take up as much memory as possible, and
give it up only when the OS tells it (from a high level view). That's part
of what you sign up for when you use .NET. I'd work on educating your
customers to NOT look at task manager in order to determine whether or not
there is a memory leak. Rather, they should look at the performance
counters (many of which exist for .NET) which give a MUCH more clear
performance picture.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:P3******** ***********@tor nado.texas.rr.c om...
Nicholas,

Thanks for the quick reply. Unfortunately I'm not using .NET 2.0 (yet!),
so I can't use Generics.

Would looping over chars like that slow things down significantly? Also,
is the char[] for each string cached with the string, or is a new one
created when you call things like ToCharArray() or foreach() on the string
(not every loop iteration, but on the first iteration)? Wouldn't I just be
replacing a new string instance with a new char[] and not get any net gain
over just calling .Trim()?

In your opinion, if I weren't against unsafe code, could I make this
significantly faster, or would it not afford me much difference?

As far as performance, on some of our clients' instances, memory growth is
rapid. It seems the more memory they have, the faster it grows which leads
me to believe that the GC is being lax since it has so much free memory
and doesn't see the need to aggressively collect memory. But it bothers
our clients and they perceive this to be a memory leak.

I realize it's an education issue, but I want to make sure that I'm
educating them correctly, as opposed to just making up a B.S. excuse and
Jedi hand-waving about the GC stuff.

Also, it's not an ASP.NET application, it's an ASP app that used to call
into VB6 COM objects. We've replaced the VB6 objects with .NET objects
exposing a "compatibil ity layer" that has a ComVisible API that is
identical (though not binary compatible) with the old VB6 stuff.
Late-bound clients don't know the difference other than a different ProgID
for the COM objects.

So we're dealing with the wkst GC, as far as I know (since only ASP.NET
uses svr unless you host the CLR yourself, from what I understand). I'm
not sure how I'd even do that in an ASP/COM-interop situation, but,
assuming it's possible, would writing our own CLR host to use the svr GC
help matters at all?

Most of our clients' servers are dual-or-more processor boxes.

Thanks again,
Chad Myers

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote
in message news:Oz******** *****@TK2MSFTNG P15.phx.gbl...
Chad,

For the first scenario, your solution should give you an increase.

For the second scenario, you should use reflection once to get a
reference to the internal static character array WhitespaceChars on the
string class. Then, you can write a method which will cycle through a
string passed to it, like so:

public static bool TrimIsNullOrEmp ty(string value)
{
// If null, then get out.
if (value == null)
{
// Return true.
return true;
}

// Cycle through the characters in the string. If the character is
not found
// in the whitespace array, return false, otherwise, when done, return
true.
foreach (char c in value)
{
// If the character is not found in the WhitespaceArray , then
return
// false.
if (Array.IndexOf< char>(Whitespac eArray, char) == -1)
{
// Return false.
return false;
}
}

// Return true, the string is full of whitespace.
return true;
}

I used the generic version of the IndexOf method on the Array class in
order to eliminate boxing. Also, if you really want to squeeze out every
last bit of performance from this, you can take the WhitespaceArray and
use the characters as keys in a dictionary. The number of whitespace
characters is 25 (right now, that is). However, if your strings
typically are padded with spaces, then you could get a big speed boost by
copying the array initially, and then placing the space character as the
first element in the array (which would cause most of the calls to
IndexOf to return very quickly, probably quicker than a lookup in a
dictionary).

I am curious though, are you seeing a performance issue, or do you
just see the numbers and are worried about them? ASP.NET applications
tend to get in a nice groove with the GC over time.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:2r******** **********@torn ado.texas.rr.co m...
I've been perf testing an application of mine and I've noticed that
there are a lot (and I mean A LOT -- megabytes and megabytes of 'em)
System.String instances being created.

I've done some analysis and I'm led to believe (but can't yet
quantitatively establish as fact) that the two basic culprits are a lot
of calls to:

1.) if( someString.ToLo wer() == "somestring " )

and

2.) if( someString != null && someString.Trim ().Length > 0 )
ToLower() generates a new string instance as does Trim().

I believe that these are getting called many times and churning up a
bunch of strings faster than the GC can collect them, or perhaps there's
some weird interning/caching thing going on. Regardless, the number of
string instances grows and grows. It gets bumped down occasionally, but
it's basically 5 steps forward, 1 back.

For reference, this is an ASP application calling into .NET ComVisible
objects. So I assume this uses the workstation GC, right?
Anyhow, so I think that I can solve problem (1) with String.Compare( )
which can perform in-place case-insensitive comparisons without
generating new string instances.

Problem (2), however, is more complicated. There doesn't appear to be a
TrimmedLength or any type of method or property that can give me the
length of a string, minus whitespace and without generating a new string
instance, in the BCL.

I suppose I could do some unsafe, or even unmanaged code (which is what
MSFT did for all their string handling stuff inside System.String and
using the COMString stuff), but I'd like to try to avoid that, or at
least use a library that's already written and well tested.

Any thoughts?

Thanks in advance,
Chad Myers



Nov 17 '05 #9
Chad,

When you use the indexer on the string, it does not create a new
character array representing the whole string. Rather, it just fetches the
character and returns a copy of that single character to the user. A
character array is never created for the return value of an indexer.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Chad Myers" <cm****@N0.SP4M .austin.rr.com> wrote in message
news:g9******** ***********@tor nado.texas.rr.c om...
KH,

Hrm, that's a good idea. In your first suggestion, I'm afraid of indexing
the char[] in the strings because I'm not sure when the char[] is created
(does it always tag along with the string, or is it only created the first
time you try to access the char[] -- through the indexer or through a call
to ToCharArray, etc).

But this suggestion just might work...

I'll look into it and let everyone know how it goes.

Thanks again everyone.

Sincerely,
Chad

"KH" <KH@discussions .microsoft.com> wrote in message
news:0F******** *************** ***********@mic rosoft.com...
Better yet (I didn't notice this overload before) ...

string str = " lalala ";

// Be sure to check that the string variable is not a null reference
// and its length is at least 1, otherwise you'll get index out of range
exceptions

if (Char.IsWhiteSp ace(str, 0) || Char.IsWhiteSpa ce(str, str.Length -1))
{
str = str.Trim();
}


Nov 17 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
1559
by: rawCoder | last post by:
Hi, Consider a server which receives delimiter based string data from client. It needs to process this data very fast. Now if its built in C++, one obvious idea would be to put the string on heap as char* and then pass the pointer around, delimiter separated fields will be accessed via pointers as well ( <map> of pointers to fields ). this will mean that there is no extensive performance nor memory consumption.
4
3103
by: Thomas Christmann | last post by:
Hi! First let me apologize for asking this question when there are so many answers to it on Google, but most of them are really contradicting, and making what I want to do very performant is crucial to my project. So, here's what I have: My C programm connects to a database and gets ca. 50-100K domain name/file path pairs. Those pairs have to be cached by my application. Building the cache may take a second or two, but retrieving from...
4
2423
by: Sam | last post by:
Hi, i'm not very familiar with string operations in vb.net. How can I simply do the following: string1 : MM/dd/yyyy string2 : yyyy MM dd I want MM to be after dd in each of those string:
7
2705
by: Skybuck Flying | last post by:
Hello, The objective of this contest is to set and clear a bit at an arbitrary memory address as fast as possible. Implement one or multiple prototypes to take part in the contest: // 8 bit versions // 1 in 256 bits procedure SetBit_8bit( BaseAddress : pointer; BitIndex : byte );
8
1788
by: Mugunth | last post by:
I'm writing a search engine crawler for indexing local files in C# My dataset is about 38000 XML files and as of now, I've successfully parsed the file, and tokenized it. But, it's surprising to find that, string operations gradually becoming slower... The system crunches 8200 files in the first 10 seconds, but is able to do only 5000 in the next 10, and then 3500 in the next 10 and it reduces gradually... It takes about 75 seconds...
3
1672
by: kelvin.koogan | last post by:
Using C++/CLI but I would imagine C# is the same. What is the fastest to do the following operations 1) Compare two Strings without case-sensitivity. 2) Take a group of objects with 4 string fields and tabulate them, so each field is in a column, in a single String, one line per object with \n separating them, calculating the minimum width required for each column and them formatting the rows so all the fields in each
0
9522
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10111
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9902
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8770
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7327
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6603
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5364
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3866
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3446
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.