Can the compiler optimize away ToString() on a string? - c#

I'm sure everyone's encountered their share of developers who love the ToString() method. We've all likely seen code similar to the following:
public static bool CompareIfAnyMatchesOrHasEmpty(List<string> list1, List<string> list2)
{
bool result = false;
foreach (string item1 in list1)
{
foreach (string item2 in list2)
{
if (item1.ToString() == item2.ToString())
{
result = true;
}
if (item1.ToString() == "")
{
result = true;
}
}
}
return result;
}
What I'm wondering is if the ToString() method (the empty, no formatting one) can be optimized away by the compiler? My assumption is that it does not, since it's originally defined on object. Thus I provide this second question, on if any effort to cleanup such instances would be worthwhile?

The C# compiler will not optimize this away. However, at runtime, I believe this will likely get inlined by the JIT compiler in the CLR, as string.ToString() just returns itself.
String.ToString is even declared with TargetedPatchingOptOutAttribute, which allows it to be inlined by NGEN as well when it's called from other assemblies, so it's obviously an inline target.

It certainly could be optimized away by the compiler, but they probably don't because it's trivial. Before deciding whether any optimization is worthwhile, try some tests first. Let's try it!
List<string> strings = Enumerable.Range(1, 10000000).Select(x => Guid.NewGuid().ToString()).ToList();
var sw= Stopwatch.StartNew();
foreach (var str in strings) {
if (!str.ToString().Equals(str.ToString())) {
throw new ApplicationException("The world is ending");
}
}
sw.Stop();
Console.WriteLine("Took: " + sw.Elapsed.TotalMilliseconds);
sw = Stopwatch.StartNew();
foreach (var str in strings) {
if (!str.Equals(str)) {
throw new ApplicationException("The world is ending");
}
}
sw.Stop();
Console.WriteLine("Took: " + sw.Elapsed.TotalMilliseconds);
Ok, so we're in a loop with 10 million items. How long does the tostring (called twice) version take compared to the non tostring version?
Here's what I get on my machine:
Took: 261.6189
Took: 231.2615
So, yeah. I saved 30 whole milliseconds over 10 million iterations. So...yeah, I'm going to say no, not worth it. At all.
Now, should the code be changed because it's stupid? Yes. I would make the argument as, "This is unnecessary and makes me think at a glance that this is NOT a string. It takes me brain cycles to process, and serves literally no purpose. Don't do it." Don't argue from an optimization point of view.

Related

Performance char vs string

Just out of curiousity (not really expecting a measurable result) which of the following codes are better in case of performance?
private void ReplaceChar(ref string replaceMe) {
if (replaceMe.Contains('a')) {
replaceMe=replaceMe.Replace('a', 'b');
}
}
private void ReplaceString(ref string replaceMe) {
if (replaceMe.Contains("a")) {
replaceMe=replaceMe.Replace("a", "b");
}
}
In the first example I use char, while in the second using strings in Contains() and Replace()
Would the first one have better performance because of the less memory-consuming "char" or does the second perform better, because the compiler does not have to cast in this operation?
(Or is this all nonsense, cause the CLR generates the same code in both variations?)
If you have two horses and want to know which is faster...
String replaceMe = new String('a', 10000000) +
new String('b', 10000000) +
new String('a', 10000000);
Stopwatch sw = new Stopwatch();
sw.Start();
// String replacement
if (replaceMe.Contains("a")) {
replaceMe = replaceMe.Replace("a", "b");
}
// Char replacement
//if (replaceMe.Contains('a')) {
// replaceMe = replaceMe.Replace('a', 'b');
//}
sw.Stop();
Console.Write(sw.ElapsedMilliseconds);
I've got 60 ms for Char replacement and 500 ms for String one (Core i5 3.2GHz, 64-bit, .Net 4.6). So
replaceMe = replaceMe.Replace('a', 'b')
is about 9 times faster
We can't know for sure without testing the code since most of the replacing is done inside the CLR and it heavily optimized.
What we can say is this: replacing a char has some performance benefits since the code is simpler and the outcome is more predictable: replacing a char will always yield the same number of characters as the original for example.
In the performance of the replacing itself doesn't matter too much. In a tight loop, the allocation and garbage collection of the 'old' string will have a bigger impact than the replacement itself.

Remove null check after lazy initialization

When one decides to use lazy initialization, he usually has to pay for it.
class Loafer
{
private VeryExpensiveField field;
private VeryExpensiveField LazyInitField()
{
field = new VeryExpensiveField();
// I wanna here remove null check from accessor, but how?
return field;
}
property Field { get { return field ?? LazyInitField(); } }
}
Basically, he has to check every time if his backing field has null/nil value. What if he could escape from this practice? When you successfully initialize the field, you can rid of this check, right?
Unfortunately, majority of production languages do not allow you to modify their functions in run-time, especially add or remove single instructions from the function body though it would be helpful if used wisely. However, in C#, you can use delegates (initially I discovered them and afterwards realized why native languages having function pointers for) and events mechanism to imitate such behavior with consequent lack of performance, because null-checks just move onto lower level, but do not disappear completely. Some languages, e.g. LISP and Prolog, allow you to modify their code easily, but they are hardly can be treated as production languages.
In native languages like Delphi and C/C++ it seems better to write two functions, safe and rapid, call them by pointer and switch this pointer to rapid version after initialization. You can even allow compiler or IDE to generate code to do this without additional headache. But as #hvd mentioned, this can even decrease speed, because CPU will not know that those functions are almost the same, thus will not prefetch them into it's cache.
Yes, I'm performance maniac seeking for performance without explicit problem, just to feed my curiosity. What common approaches are exist to develop such functionality?
Actually the laziness toolkit framework is not always that important, when you compare it's overhead to the actual computation.
There are many approaches.
You can use Lazy, a self modifying lambda setup, a boolean or whatever suits your workflow best.
Lazy evaluation toolkit's overhead is only important to consider when you have some repeated computation.
My code example with a micro benchmark explores the comparative overhead of lazy computation in context of an accompanying more expensive operation in a loop.
You can see that laziness toolkit's overhead is neglectible even when used along with a relatively chip payload operation.
void Main()
{
// If the payload is small, laziness toolkit is not neglectible
RunBenchmarks(i => i % 2 == 0, "Smaller payload");
// Even this small string manupulation neglects overhead of laziness toolkit
RunBenchmarks(i => i.ToString().Contains("5"), "Larger payload");
}
void RunBenchmarks(Func<int, bool> payload, string what)
{
Console.WriteLine(what);
var items = Enumerable.Range(0, 10000000).ToList();
Func<Func<int, bool>> createPredicateWithBoolean = () =>
{
bool computed = false;
return i => (computed || (computed = Compute())) && payload(i);
};
items.Count(createPredicateWithBoolean());
var sw = Stopwatch.StartNew();
Console.WriteLine(items.Count(createPredicateWithBoolean()));
sw.Stop();
Console.WriteLine("Elapsed using boolean: {0}", sw.ElapsedMilliseconds);
Func<Func<int, bool>> createPredicate = () =>
{
Func<int, bool> current = i =>
{
var computed2 = Compute();
current = j => computed2;
return computed2;
};
return i => current(i) && payload(i);
};
items.Count(createPredicate());
sw = Stopwatch.StartNew();
Console.WriteLine(items.Count(createPredicate()));
sw.Stop();
Console.WriteLine("Elapsed using smart predicate: {0}", sw.ElapsedMilliseconds);
Console.WriteLine();
}
bool Compute()
{
return true; // not important for the exploration
}
Output:
Smaller payload
5000000
Elapsed using boolean: 161
5000000
Elapsed using smart predicate: 182
Larger payload
5217031
Elapsed using boolean: 1980
5217031
Elapsed using smart predicate: 1994
FWIW with the help of Spring4D this can also be done in Delphi:
var
field: Lazy<VeryExpensiveField>;
begin
field :=
function: VeryExpensiveField
begin
Result := VeryExpensiveField.Create;
end;

Using task parallel library in IEnumerable implementation to achieve speed improvement

Following code is simplified version of the code that I am trying to optimize.
void Main()
{
var words = new List<string> {"abcd", "wxyz", "1234"};
foreach (var character in SplitItOut(words))
{
Console.WriteLine (character);
}
}
public IEnumerable<char> SplitItOut(IEnumerable<string> words)
{
foreach (string word in words)
{
var characters = GetCharacters(word);
foreach (char c in characters)
{
yield return c;
}
}
}
char[] GetCharacters(string word)
{
Thread.Sleep(5000);
return word.ToCharArray();
}
I cannot change the signature of method SplitItOut.The GetCharacters method is expensive to call but is thread safe. The input to SplitItOut method can contain 100,000+ entries and a single call to GetCharacters() method can take around 200ms. It can also throw exceptions which I can ignore. Order of the results do not matter.
In my first attempt I came up with following implementation using TPL which speeds up the things quite a bit, but is blocking till I am done processing all the words.
public IEnumerable<char> SplitItOut(IEnumerable<string> words)
{
Task<char[][]> tasks = Task<char[][]>.Factory.StartNew(() =>
{
ConcurrentBag<char[]> taskResults = new ConcurrentBag<char[]>();
Parallel.ForEach(words,
word =>
{
taskResults.Add(GetCharacters(word));
});
return taskResults.ToArray();
});
foreach (var wordResult in tasks.Result)
{
foreach (var c in wordResult)
{
yield return c;
}
}
}
I am looking for any better implementation for method SplitItOut() than this. Lower processing time is my priority here.
If I'm reading your question correctly, you're not looking to just speed up the parallel processing that creates the chars from the words - you would like your enumerable to produce each one as soon as it's ready. With the implementation you currently have (and the other answers I currently see), the SplitItOut will wait until all of the words have been sent to GetCharacters, and all results returned before producing the first one.
In cases like this, I like to think of things as splitting my process into producers and a consumer. Your producer thread(s) will take the available words and call GetCharacters, then dump the results somewhere. The consumer will yield up characters to the caller of SplitItOut as soon as they are ready. Really, the consumer is the caller of SplitItOut.
We can make use of the BlockingCollection as both a way to yield up the characters, and as the "somewhere" to put the results. We can use the ConcurrentBag as a place to put the words that have yet to be split:
static void Main()
{
var words = new List<string> { "abcd", "wxyz", "1234"};
foreach (var character in SplitItOut(words))
{
Console.WriteLine(character);
}
}
static char[] GetCharacters(string word)
{
Thread.Sleep(5000);
return word.ToCharArray();
}
No changes to your main or GetCharacters - since these represent your constraints (can't change caller, can't change expensive operation)
public static IEnumerable<char> SplitItOut(IEnumerable<string> words)
{
var source = new ConcurrentBag<string>(words);
var chars = new BlockingCollection<char>();
var tasks = new[]
{
Task.Factory.StartNew(() => CharProducer(source, chars)),
Task.Factory.StartNew(() => CharProducer(source, chars)),
//add more, tweak away, or use a factory to create tasks.
//measure before you simply add more!
};
Task.Factory.ContinueWhenAll(tasks, t => chars.CompleteAdding());
return chars.GetConsumingEnumerable();
}
Here, we change the SplitItOut method to do four things:
Initialize a concurrentbag with all of the words we wish to split. (side note: If you want to enumerate over words on demand, you can start a new task to push them in rather than doing it in the constructor)
Start up our char "producer" Tasks. You can start a set number, use a factory, whatever. I suggest not going task-crazy before you measure.
Signal the BlockingCollection that we are done when all tasks have completed.
"Consume" all of the produced chars (we make it easy on ourselves and just return an IEnumerable<char> rather than foreach and yield, but you could do it the long way if you wish)
All that's missing is our producer implementation. I've expanded out all the linq shortcuts to make it clear, but it's super simple:
private static void CharProducer(ConcurrentBag<string> words, BlockingCollection<char> output)
{
while(!words.IsEmpty)
{
string word;
if(words.TryTake(out word))
{
foreach (var c in GetCharacters(word))
{
output.Add(c);
}
}
}
}
This simply
Takes a word out of the ConcurrentBag (unless it's empty - if it is, task is done!)
Calls the expensive method
Puts the output in the BlockingCollection
I put your code through the profiler built into Visual Studio, and it looks like the overhead of the Task was hurting you. I refactored it slightly to remove the Task, and it improved the performance a bit. Without your actual algorithm and dataset, it's hard to tell exactly what the issue is or where the performance can be improved. If you have VS Premium or Ultimate, there are built-in profiling tools that will help you out a lot. You can also grab the trial of ANTS.
One thing to bear in mind: Don't try to prematurely optimize. If your code is performing acceptably, don't add stuff to possibly make it faster at the expense of readability and maintainability. If it's not performing to an acceptable level, profile it before you start messing with it.
In any case, here's my refactoring of your algorithm:
public static IEnumerable<char> SplitItOut(IEnumerable<string> words)
{
var taskResults = new ConcurrentBag<char[]>();
Parallel.ForEach(words, word => taskResults.Add(GetCharacters(word)));
return taskResults.SelectMany(wordResult => wordResult);
}

Which is faster in a loop: calling a property twice, or storing the property once?

This is more of an academic question about performance than a realistic 'what should I use' but I'm curious as I don't dabble much in IL at all to see what's constructed and I don't have a large dataset on hand to profile against.
So which is faster:
List<myObject> objs = SomeHowGetList();
List<string> strings = new List<string>();
foreach (MyObject o in objs)
{
if (o.Field == "something")
strings.Add(o.Field);
}
or:
List<myObject> objs = SomeHowGetList();
List<string> strings = new List<string>();
string s;
foreach (MyObject o in objs)
{
s = o.Field;
if (s == "something")
strings.Add(s);
}
Keep in mind that I don't really want to know the performance impact of the string.Add(s) (as whatever operation needs to be done can't really be changed), just the performance difference between setting s each iteration (let's say that s can be any primitive type or string) verses calling the getter on the object each iteration.
Your first option is noticeably faster in my tests. I'm such flip flopper! Seriously though, some comments were made about the code in my original test. Here's the updated code that shows option 2 being faster.
class Foo
{
public string Bar { get; set; }
public static List<Foo> FooMeUp()
{
var foos = new List<Foo>();
for (int i = 0; i < 10000000; i++)
{
foos.Add(new Foo() { Bar = (i % 2 == 0) ? "something" : i.ToString() });
}
return foos;
}
}
static void Main(string[] args)
{
var foos = Foo.FooMeUp();
var strings = new List<string>();
Stopwatch sw = Stopwatch.StartNew();
foreach (Foo o in foos)
{
if (o.Bar == "something")
{
strings.Add(o.Bar);
}
}
sw.Stop();
Console.WriteLine("It took {0}", sw.ElapsedMilliseconds);
strings.Clear();
sw = Stopwatch.StartNew();
foreach (Foo o in foos)
{
var s = o.Bar;
if (s == "something")
{
strings.Add(s);
}
}
sw.Stop();
Console.WriteLine("It took {0}", sw.ElapsedMilliseconds);
Console.ReadLine();
}
Most of the time, your second code snippet should be at least as fast as the first snippet.
These two code snippets are not functionally equivalent. Properties are not guaranteed to return the same result across individual accesses. As a consequence, the JIT optimizer is not able to cache the result (except for trivial cases) and it will be faster if you cache the result of a long running property. Look at this example: why foreach is faster than for loop while reading richtextbox lines.
However, for some specific cases like:
for (int i = 0; i < myArray.Length; ++i)
where myArray is an array object, the compiler is able to detect the pattern and optimize the code and omit the bound checks. It might be slower if you cache the result of Length property like:
int len = myArray.Length;
for (int i = 0; i < myArray.Length; ++i)
It really depends on the implementation. In most cases, it is assumed (as a matter of common practice / courtesy) that a property is inexpensive. However, it could that each "get" does a non-cached search over some remote resource. For standard, simple properties, you'll never notice a real difference between the two. For the worst-case, fetch-once, store and re-use will be much faster.
I'd be tempted to use get twice until I know there is a problem... "premature optimisation", etc... But; if I was using it in a tight loop, then I might store it in a variable. Except for Length on an array, which has special JIT treatment ;-p
Generally the second one is faster, as the first one recalculates the property on each iteration.
Here is an example of something that could take significant amount of time:
var d = new DriveInfo("C:");
d.VolumeLabel; // will fetch drive label on each call
Storing the value in a field is the faster option.
Although a method call doesn't impose a huge overhead, it far outweighs storing the value once to a local variable on the stack and then retrieving it.
I for one do it consistently.

c# performance: type comparison vs. string comparison

Which is faster? This:
bool isEqual = (MyObject1 is MyObject2)
Or this:
bool isEqual = ("blah" == "blah1")
It would be helpful to figure out which one is faster. Obviously, if you apply .ToUpper() to each side of the string comparison like programmers often do, that would require reallocating memory which affects performance. But how about if .ToUpper() is out of the equation like in the above sample?
I'm a little confused here.
As other answers have noted, you're comparing apples and oranges. ::rimshot::
If you want to determine if an object is of a certain type use the is operator.
If you want to compare strings use the == operator (or other appropriate comparison method if you need something fancy like case-insensitive comparisons).
How fast one operation is compared to the other (no pun intended) doesn't seem to really matter.
After closer reading, I think that you want to compare the speed of string comparisions with the speed of reference comparisons (the type of comparison used in the System.Object base type).
If that's the case, then the answer is that reference comparisons will never be slower than any other string comparison. Reference comparison in .NET is pretty much analogous to comparing pointers in C - about as fast as you can get.
However, how would you feel if a string variable s had the value "I'm a string", but the following comparison failed:
if (((object) s) == ((object) "I'm a string")) { ... }
If you simply compared references, that might happen depending on how the value of s was created. If it ended up not being interned, it would not have the same reference as the literal string, so the comparison would fail. So you might have a faster comparison that didn't always work. That seems to be a bad optimization.
According to the book Maximizing .NET Performance
the call
bool isEqual = String.Equals("test", "test");
is identical in performance to
bool isEqual = ("test" == "test");
The call
bool isEqual = "test".Equals("test");
is theoretically slower than the call to the static String.Equals method, but I think you'll need to compare several million strings in order to actually detect a speed difference.
My tip to you is this; don't worry about which string comparison method is slower or faster. In a normal application you'll never ever notice the difference. You should use the way which you think is most readable.
The first one is used to compare types not values.
If you want to compare strings with a non-sensitive case you can use:
string toto = "toto";
string tata = "tata";
bool isEqual = string.Compare(toto, tata, StringComparison.InvariantCultureIgnoreCase) == 0;
Console.WriteLine(isEqual);
How about you tell me? :)
Take the code from this Coding Horror post, and insert your code to test in place of his algorithm.
Comparing strings with a "==" operator compares the contents of the string vs. the string object reference. Comparing objects will call the "Equals" method of the object to determine whether they are equal or not. The default implementation of Equals is to do a reference comparison, returning True if both object references are the same physical object. This will likely be faster than the string comparison, but is dependent on the type of object being compared.
I'd assume that comparing the objects in your first example is going to be about as fast as it gets since its simply checking if both objects point to the same address in memory.
As it has been mentioned several times already, it is possible to compare addresses on strings as well, but this won't necessarily work if the two strings are allocated from different sources.
Lastly, its usually good form to try and compare objects based on type whenever possible. Its typically the most concrete method of identification. If your objects need to be represented by something other than their address in memory, its possible to use other attributes as identifiers.
If I understand the question and you really want to compare reference equality with the plain old "compare the contents": Build a testcase and call object.ReferenceEquals compared against a == b.
Note: You have to understand what the difference is and that you probably cannot use a reference comparison in most scenarios. If you are sure that this is what you want it might be a tiny bit faster. You have to try it yourself and evaluate if this is worth the trouble at all..
I don't feel like any of these answers address the actual question. Let's say the string in this example is the type's name and we're trying to see if it's faster to compare a type name or the type to determine what it is.
I put this together and to my surprise, it's about 10% faster to check the type name string than the type in every test I ran. I intentionally put the simplest strings and classes into play to see if it was possible to be faster, and turns out it is possible. Not sure about more complicated strings and type comparisons from heavily inherited classes. This is of course a micro-op and may possibly change at some point in the evolution of the language I suppose.
In my case, I was considering a value converter that switches based on this name, but it could also switch over the type since each type specifies a unique type name. The value converter would figure out the font awesome icon to show based on the type of item presented.
using System;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApp1
{
public sealed class A
{
public const string TypeName = "A";
}
public sealed class B
{
public const string TypeName = "B";
}
public sealed class C
{
public const string TypeName = "C";
}
class Program
{
static void Main(string[] args)
{
var testlist = Enumerable.Repeat(0, 100).SelectMany(x => new object[] { new A(), new B(), new C() }).ToList();
int count = 0;
void checkTypeName()
{
foreach (var item in testlist)
{
switch (item)
{
case A.TypeName:
count++;
break;
case B.TypeName:
count++;
break;
case C.TypeName:
count++;
break;
default:
break;
}
}
}
void checkType()
{
foreach (var item in testlist)
{
switch (item)
{
case A _:
count++;
break;
case B _:
count++;
break;
case C _:
count++;
break;
default:
break;
}
}
}
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
checkTypeName();
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
sw.Restart();
for (int i = 0; i < 100000; i++)
{
checkType();
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
}
}

Categories