Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I am wondering what kind of optimization techniques people often use nowadays. I have seen people do caching all the time with dictionary and all. Is the trading space for speed the only way to go?
Really it's about your choice in algorithms. Usually there is no "silver bullet" for optimization.
For example, using a StringBuilder instead of concatenation can make your code significantly faster, but there is a tradeoff. If you aren't concatenating huge sets of strings, the memory and time it takes to initialize StringBuilder is worse than just using regular concatenation. There are a lot of examples of this throughout the framework, such as dictionary caching as you mentioned in your question.
The only general optimization you can really learn and apply to your coding throughout your day is the performance hit from boxing/unboxing (heap vs. stack). To do this you need to learn what it's about and how to avoid, or reduce the need to do it.
Microsoft's MSDN documentation has 2 articles on performance that give a lot of good general purpose techniques to use (they're really just different versions of the same article).
http://msdn.microsoft.com/en-us/library/ms173196.aspx
http://msdn.microsoft.com/en-us/library/ms173196(VS.80).aspx
I will suggest below
1. Knowing when to use StringBuilder
You must have heard before that a StringBuilder object is much faster at appending strings together than normal string types.
The thing is StringBuilder is faster mostly with big strings. This means if you have a loop that will add to a single string for many iterations then a StringBuilder class is definitely much faster than a string type.
However if you just want to append something to a string a single time then a StringBuilder class is overkill. A simple string type variable in this case improves on resources use and readability of the C# source code.
Simply choosing correctly between StringBuilder objects and string types you can optimize your code.
2. Comparing Non-Case-Sensitive Strings
In an application sometimes it is necessary to compare two string variables, ignoring the cases. The tempting and traditionally approach is to convert both strings to all lower case or all upper case and then compare them, like such:
str1.ToLower() == str2.ToLower()
However repetitively calling the function ToLower() is a bottleneck in performace. By instead using the built-in string.Compare() function you can increase the speed of your applications.
To check if two strings are equal ignoring case would look like this:
string.Compare(str1, str2, true) == 0 //Ignoring cases
The C# string.Compare function returns an integer that is equal to 0 when the two strings are equal.
3. Use string.Empty
This is not so much a performance improvement as it is a readability improvement, but it still counts as code optimization. Try to replace lines like:
if (str == "")
with:
if (str == string.Empty)
This is simply better programming practice and has no negative impact on performance.
Note, there is a popular practice that checking a string's length to be 0 is faster than comparing it to an empty string. While that might have been true once it is no longer a significant performance improvement. Instead stick with string.Empty.
4. Replace ArrayList with List<>
ArrayList are useful when storing multiple types of objects within the same list. However if you are keeping the same type of variables in one ArrayList, you can gain a performance boost by using List<> objects instead.
Take the following ArrayList:
ArrayList intList = new ArrayList();
intList.add(10);
return (int)intList[0] + 20;
Notice it only contains intergers. Using the List<> class is a lot better. To convert it to a typed List, only the variable types need to be changed:
List<int> intList = new List<int>();
intList.add(10)
return intList[0] + 20;
There is no need to cast types with List<>. The performance increase can be especially significant with primitive data types like integers.
5. Use && and || operators
When building if statements, simply make sure to use the double-and notation (&&) and/or the double-or notation (||), (in Visual Basic they are AndAlso and OrElse).
If statements that use & and | must check every part of the statement and then apply the "and" or "or". On the other hand, && and || go thourgh the statements one at a time and stop as soon as the condition has either been met or not met.
Executing less code is always a performace benefit but it also can avoid run-time errors, consider the following C# code:
if (object1 != null && object1.runMethod())
If object1 is null, with the && operator, object1.runMethod()will not execute. If the && operator is replaced with &, object1.runMethod() will run even if object1 is already known to be null, causing an exception.
6. Smart Try-Catch
Try-Catch statements are meant to catch exceptions that are beyond the programmers control, such as connecting to the web or a device for example. Using a try statement to keep code "simple" instead of using if statements to avoid error-prone calls makes code incredibly slower. Restructure your source code to require less try statements.
7. Replace Divisions
C# is relatively slow when it comes to division operations. One alternative is to replace divisions with a multiplication-shift operation to further optimize C#. The article explains in detail how to make the conversion.
REFERENCE
There are often problems with algorithms as well, usually when something expensive is done inside of a loop. Generally, the first thing you do is profile your application, which will tell you the slowest part(s) of the application. Generally, what you do to speed up your application depends upon what you find. For example, if your application mimics a file system, it may be that you're calling the database recursively to travel up the tree (for instance). You may optimise that case by changing those recursive calls into one flattened database call that returns all of the data in one call.
Again, the answer is, as always, 'it depends'. However, more examples and advice can be found in Rico Mariani's blog (browse back a few years, as his focus has shifted):
Depends on a lot of things, really.
As an example, when memory becomes an issue and a lot of temporary objects are being created I tend to use object pools. (Having a garbage-collector is not a reason to not take care of memory allocation). If speed is what matters then I might use unsafe pointers to work with arrays.
Either way, if you find yourself struggling too much with optimization techniques in a c#/.net application you probably chose the wrong language/platform.
In general, make sure you understand the time complexity of different algorithms, and use that knowledge to choose your implementations wisely.
For .NET in particular, this article goes into great detail about optimizing code deployed to the CLR (though it's also relevant for Java, or any other modern platform), and is one of the best guides I've ever read:
http://msdn.microsoft.com/en-us/library/ms973852.aspx
To distill the article into one sentence: Nothing affects the speed of a .NET application (with sensible algorithms) more than the memory-footprint of its objects. Be very careful to minimize your memory consumption.
I would recommend Effective C# by Bill Wagner (first edition and second edition). He goes through a number of language constructs and techniques and explains which ones are faster and why. He touches on a lot of best practices as well.
More often than not, however, optimizing your algorithm will give you far better results than using any kind of language / optimization technique.
Related
Consider this code:
var (mult, sum) = MultSum(a, b);
and
var (_, sum) = MultSum(a, b);
Question 1.
If I use discard instead of a variable name, does it have performance benefit? eg. by reducing assignment operations.
Question 2.
Is there any way to write the MultSum smart enough so it doesn't calculate the discards!?
If I use discard instead of a variable name, does it have performance benefit? eg. by reducing assignment operations.
In your particular case it is unlikely that there would be a benefit in performance. The tuple that is returned is assigned to temporary storage; you've just not given a name to one part of that storage.
Now, if you had an expression that had discards that were entire values, not fragments of a tuple, then the compiler and the jitter can be smart about not allocating any storage on the short-term pool for the result, or re-using existing storage that was already allocated. Note that by "short-term pool" I effectively mean "activation record on the stack" or "registers". This could, in theory, lead to better register allocation or smaller frames (and therefore better locality of reference) and that in turn could save you entire nanoseconds.
Nano-optimizations are generally not worth it; there is almost always a better bang-for-buck performance problem to attack. But if you think it might be relevant for your scenario, measure it and see. That is the only way to know if there is a relevant performance difference. Get out a nano-scale stopwatch, run the code both ways, and see which one is faster.
The benefit you should be attempting to accrue by using discards is the "make my program easier to understand" benefit. Programmers are expensive; optimize for making your code easy for future programmers to read, understand and modify.
Is there any way to write the MultSum smart enough so it doesn't calculate the discards!?
Yes. Write your program in Haskell. Haskell will avoid performing calculations whose results are never used. C# is not such a language.
Sorry for my last question, my code was so stupid.
My base situation is: I want to construct a state tree which has 8! items in the last state. so the total count of iterations is about 100.000 (8!*2 + 7! + 6! + ... )
it currently takes less than one second, i need to construct it every time my artificial intelligence is making a move. Of course, the alpha/beta search is a solution but before thinking of that i want to optimize my code so i really have the best possible performance.
what i already did:
tried to replace every LINQ function with precalculations or collections with faster access (Dictionary), more precalculations for skipping whole operations, of course, some approximations to spare heavy calculations, using List constructors only when there's actually a change, if not, just use the reference.
there'll be more calculations coming so i really need more ideas for reducing. maybe something about what collection is fastest for my purpose.
My code
It's about the BuildChildNodes function and the called TryCollect function. My Constructor is doing some little precalculations. my state tree knows everything, even the cards which aren't actually shown.
as the comment came up: i'm not asking you to read and understand my code to provide content-wise advices. i'm asking you about the functions, operators, data types and classes i'm using and if there could be make a replacement which runs a bit faster. e.g. if there's a faster collection for my purpose or if you have a better idea to replace the collections constructor with a faster method reagarding of adding and removing afterwards.
Edit: okay List is definitely the best type i can use. i tried [] Arrays and even Dictionaries () and last of all i even tried LinkedLists. All with a significant loss.
I can see that RemoveAt() could be expensive at it is proportional to the size of the list.
You can always use the Visual Studio performance profiler to find out where you should optimize your code the most.
If you can find a way to use fixed-size arrays that you allocate when your program starts, instead of dynamically-allocated data structures like List, you will save of lot on memory allocation management overhead.
Suppose I'm writing a parser and I need to check if the current token returned by Scanner::NextToken (for example) is one of a small set of values (say 5-10 items; few less or few more).
In this small open source project (https://github.com/gsscoder/exprengine), inside the Parser class I've declared various static arrays that I query with Array::Contains() (see Parser::Ensure() method).
I'm guessing if I can gain in performance using the same technique used in the scanner for check tokens, that is an helper method that uses an if statement (like the following):
private static bool IsLineTerminator(int c)
{
return c == 0x0A || c == 0x0D || c == 0x2028 || c == 0x2029;
}
Or maybe that also in the Scanner, I should use technique used in the Parser?
Any opinion (well motivated) will be appreciated; just don't suggest to generate parser/scanner using tools like ANTLR - I want to keep an hand-written implementation.
Regards, Giacomo
Essentially that's exactly what Array.Contains is doing. You'll have a slightly more involved call stack using Contains as it's not going to be inlined to that degree, but the basic idea of what's happening is the same. It's unlikely you'll see a dramatic performance difference, but by all means profile the two methods and see for yourself. The best way of knowing which method is faster is just to try it, not to ask random strangers.
Another option to consider for an actual algorithm change which would potentially be faster is to use a HashSet as opposed to an array. For only 4 values the speed difference is likely to be small, but a hash-based data structure is specifically designed for much faster searching. (It's at least worth testing that as well). A switch statement will also be implemented as a hash-based solution, so you could consider using that as well.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Which one of these do you prefer?
foreach(var zombie in zombies)
{
zombie.ShuffleTowardsSurvivors();
zombie.EatNearbyBrains();
}
or
zombies.Each(zombie => {
zombie.ShuffleTowardsSurvivors();
zombie.EatNearbyBrains();
});
The first. It's part of the language for a reason.
Personally, I'd only use the second, functional approach to flow control if there is a good reason to do so, such as using Parallel.ForEach in .NET 4. It has many disadvantages, including:
It's slower. It's going to introduce a delegate invocation at each element, just like you did foreach (..) { myDelegate(); }
It's non-standard, so will be more difficult to understand by most developers
If you close over any locals, you're going to force the compiler to make a closure. This can lead to strange issues if there's threading involved, plus adds completely unnecessary bloat to the assembly.
I see no reason to write your own syntax for a flow control construct that already exists in the language.
Here you're doing some very imperative things like writing a statement rather than an expression (as presumably the Each method returns no value) and mutating state (which one can only assume the methods do, as they also appear to return no value) yet you're trying to pass them off as 'functional programming' by passing a collection of statements as a delegate. This code could barely be further from the ideals and idioms of functional programming, so why try to disguise it as such?
As much as I like multi-paradigm languages such as C#, I think they are easiest to understand and maintain when paradigms are mixed at a higher level (e.g. an entire method written in either a functional or an imperative style) rather than when multiple paradigms are mixed within a single statement or expression.
If you're writing imperative code just be honest about it and use a loop. It's nothing to be ashamed of. Imperative code is not an inherently bad thing.
Second form.
In my opinion, the less language constructs and keywords you have to use, the better. C# has enough extraneous crud in it as it is.
Generally the less you have to type, the better. Seriously, how could you not want to use "var" in situations like this? Surely if being explicit was your only goal, you'd still be using hungarian notation... you have an IDE that gives you type information whenever you hover over... or of course Ctrl+Q if you're using Resharper...
#T.E.D. The performance implications of a delegate invocation are a secondary concern. If you're doing this a thousand terms sure, run dot trace and see if it's not acceptable.
#Reed Copsey: re non-standard, if a developer can't work out what ".Each" is doing then you've got more problems, heh. Hacking the language to make it nicer is one of the great joys of programming.
The lamda version is actually not slower. I just did a quick test and the delegate version is about 30% faster.
Here is the codez:
class Blah {
public void DoStuff() {
}
}
List<Blah> blahs = new List<Blah>();
DateTime start = DateTime.Now;
for(int i = 0; i < 30000000; i++) {
blahs.Add(new Blah());
}
TimeSpan elapsed = (DateTime.Now - start);
Console.WriteLine(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Allocation - {0:00}:{1:00}:{2:00}.{3:000}",
elapsed.Hours,
elapsed.Minutes,
elapsed.Seconds,
elapsed.Milliseconds));
start = DateTime.Now;
foreach(var bl in blahs) {
bl.DoStuff();
}
elapsed = (DateTime.Now - start);
Console.WriteLine(string.Format(System.Globalization.CultureInfo.CurrentCulture, "foreach - {0:00}:{1:00}:{2:00}.{3:000}",
elapsed.Hours,
elapsed.Minutes,
elapsed.Seconds,
elapsed.Milliseconds));
start = DateTime.Now;
blahs.ForEach(bl=>bl.DoStuff());
elapsed = (DateTime.Now - start);
Console.WriteLine(string.Format(System.Globalization.CultureInfo.CurrentCulture, "lambda - {0:00}:{1:00}:{2:00}.{3:000}",
elapsed.Hours,
elapsed.Minutes,
elapsed.Seconds,
elapsed.Milliseconds));
OK, So I've run more tests and here are the results.
The order of the execution(forach, lambda or lambda, foreach) didn't make much difference, lambda version was still faster:
foreach - 00:00:00.561
lambda - 00:00:00.389
lambda - 00:00:00.317
foreach - 00:00:00.337
The difference in performance is a lot less for arrays of classes. Here are the numbers for Blah[30000000]:
lambda - 00:00:00.317
foreach - 00:00:00.337
Here is the same test but Blah being a struct:
Blah[] version
lambda - 00:00:00.676
foreach - 00:00:00.437
List version:
lambda - 00:00:00.461
foreach - 00:00:00.391
Optimized build, Blah is a struct using an array.
lambda - 00:00:00.426
foreach - 00:00:00.079
Conclusion: There is no blanket answer for performance of foreach vs lambda. The answer is It depends. Here is a more scientific test for List<T>. As far as I can tell it's pretty damn efficient. If you are really concerned with performance use for(int i... loop. For iterating over a collection of a thousand customer records (example) it really doesn't matter all that much.
As far as deciding between which version to use I would put potential performance hit for lambda version way at the bottom.
Conclusion #2 T[] (where T is a value type) foreach loop is about 5 times faster for this test in an optimized build. That's the only significant difference between a Debug and Release build. So there you go, for arrays of value types use foreach, everything else - it doesn't matter.
This question contains some useful discussion, as well as a link to an MSDN blog post, on the philosophical aspects of the topic.
I think extension methods are cool, but I think break and edit-and-continue are cooler.
I'd think the second form would be tougher to optimize, as there's no way for the compiler to unroll the loop any differently for this one call than it does for anybody else's call to the Each method.
Since it was asked, I'll elaborate. The method's implementation is quite liable to be compiled separately from the code that invokes it. This means that the compiler does not know exactly how many loops it is going to have to perform.
If you use the "foreach" form then that information may be avaliable to the compiler when it is creating the code for the loop (it also may not be available, in which case no difference).
For example, if the compiler happens to know (from previous code in the same file) that the list has exactly 20 items in it, it can replace the entire loop with 20 references.
However, when the compiler creates code for the "Each" method off in its source file, it has no idea how big the caller's list is going to be. It has to support any size. The best it can do is try to find some kind of optimum unrolling for its CPU, and add extra code to loop through that and do a proper loop if it is too small for the unrolling. For a typical small loop this might even end up being slower. Of course for small loops you don't care as much....unless they happen to be inside a big loop.
As another poster mentioned, this is (and should be) a secondary concern. The important thing is which is easier to read and/or maintain, but I don't see a huge difference there.
I don't prefer either, because of what I consider to be an un-needed use of 'var'. I would write is as:
foreach(Zombie zombie in zombies){
}
But as to the Functional or foreach, for me I most definitely prefer foreach, because there doesn't seem to be a good reason for the latter.
If I have the following function, it is considered pure in that it has no side effects and will always produce the same result given the same input x.
public static int AddOne(int x) { return x + 1; }
As I understand it, if the runtime understood the functional purity it could optimize execution so that return values wouldn't have to be re-calculated.
Is there a way to achieve this kind of runtime optimization in C#? And I assume there is a name for this kind of optimization. What's it called?
Edit: Obviously, my example function wouldn't have a lot of benefit from this kind of optimization. The example was given to express the type of purity I had in mind rather than the real-world example.
As others have noted, if you want to save on the cost of re-computing a result you've already computed, then you can memoize the function. This trades increased memory usage for increased speed -- remember to clear your cache occasionally if you suspect that you might run out of memory should the cache grow without bound.
However, there are other optimizations one can perform on pure functions than memoizing their results. For example, pure functions, having no side effects, are usually safe to call on other threads. Algorithms which use a lot of pure functions can often be parallelized to take advantage of multiple cores.
This area will become increasingly important as massively multi-core machines become less expensive and more common. We have a long-term research goal for the C# language to figure out some way to take advantage of the power of pure functions (and impure but "isolated" functions) in the language, compiler and runtime. But doing so involves many difficult problems, problems about which there is little consensus in industry or academia as to the best approach. Top minds are thinking about it, but do not expect any major results any time soon.
if the calculation was a costly one, you could cache the result in a dictionary?
static Dictionary<int, int> cache = new Dictionary<int, int>();
public static int AddOne(int x)
{
int result;
if(!cache.TryGetValue(x, out result))
{
result = x + 1;
cache[x] = result;
}
return result;
}
of course, the dictionary lookup in this case is more costly than the add :)
There's another much cooler way to do functional memoization explained by Wes Dyer here: http://blogs.msdn.com/wesdyer/archive/2007/01/26/function-memoization.aspx - if you do a LOT of this caching, then his Memoize function might save you a lot of code...
I think you're looking for functional memoization
The technique you are after is memoization: cache the results of execution, keyed off the arguments passed in to the function, in an array or dictionary. Runtimes do not tend to apply it automatically, although there are certainly cases where they would. Neither C# nor .NET applies memoization automatically. You can implement memoization yourself - it's rather easy -, but doing so is generally useful only for slower pure functions where you tend to repeat calculations and where you have enough memory.
This will probably be inlined (aka inline expansion) by the compiler ...
Just make sure you compile your code with the "Optimize Code" flag set (in VS : project properties / build tab / Optimize Code)
The other thing you can do is to cache the results (aka memoization). However, there is a huge initial performance hit due to your lookup logic, so this is interesting only for slow functions (ie not an int addition).
There is also a memory impact, but this can be managed through a clever use of weak references.
As I understand it, if the runtime
understood the functional purity it
could optimize execution so that
return values wouldn't have to be
re-calculated.
In your example, the runtime WILL have to compute the result, unless x is known at compile time. In that case, your code will be further optimized through the use of constant folding
How could the compiler do that ? How does it know what values of x are going to be passed in at runtime?
and re: other answers that mention inlining...
My understanding is that inlining (as an optimization) is warranted for small functions that are used only once (or only a very few times...) not because they have no side effects...
A compiler can optimize this function through a combination of inlining (replacing a function call with the body of that function at the call site) and constant propagation (replacing an expression with no free variables with the result of that expression). For example, in this bit of code:
AddOne(5);
AddOne can be inlined:
5 + 1;
Constant propagation can then simplify the expression:
6;
(Dead code elimination can then simplify this expression even further, but this is just an example).
Knowing that AddOne() has no side effects might also enable the a compiler to perform common subexpression elimination, so that:
AddOne(3) + AddOne(3)
may be transformed to:
int x = AddOne(3);
x + x;
or by strength reduction, even:
2*AddOne(3);
There is no way to command the c# JIT compiler to perform these optimizations; it optimizes at its own discretion. But it's pretty smart, and you should feel comfortable relying on it to perform these sorts of transformations without your intervention.
Another option is to use a fody plugin https://github.com/Dresel/MethodCache
you can decorate methods that should be cached. When using this you should of course take into consideration all the comments mentioned in the other answers.