After upgrading to ReSharper5 it gives me even more useful tips on code improvements. One I see everywhere now is a tip to replace foreach-statements with LINQ queries. Take this example:
private Ninja FindNinjaById(int ninjaId)
{
foreach (var ninja in Ninjas)
{
if (ninja.Id == ninjaId)
return ninja;
}
return null;
}
This is suggested replaced with the following using LINQ:
private Ninja FindNinjaById(int ninjaId)
{
return Ninjas.FirstOrDefault(ninja => ninja.Id == ninjaId);
}
This looks all fine, and I'm sure it's no problem regarding performance to replace this one foreach. But is it something I should do in general? Or might I run into performance problems with all these LINQ queries everywhere?
You need to understand what the LINQ query is going to do "under the hood" and compare that to running your code before you can know whether you should change it. Generally, I don't mean that you need to know the exact code that will be generated, but you do need to know the basic idea of how it would go about performing the operation. In your example, I would surmise that LINQ would basically work about the same as your code and because the LINQ statement is more compact and descriptive, I would prefer it. There are times, though, when LINQ may not be the ideal choice, though probably not many. Generally I would think that just about any looping construct would be replaceable by an equivalent LINQ construct.
Let me start by saying that I love LINQ for its expressiveness and use it all the time without any problem.
There are however some differences in performance. Normally they are small enough to ignore, but in the critical path of your application, there might be times you want to optimize them away.
Here is the set of differences that you should be aware of, that could matter with performance:
LINQ uses delegate calls excessively, and delegate invocations are (a very tiny bit) slower than method invocations and of course slower than inline code.
A delegate is a method pointer inside an object. That object need to be created.
LINQ operators usually return a new object (an iterator) that allows looping through the collection. Chained LINQ operators thus create multiple new objects.
When your inner loop uses objects from outside (called closures) they have to be wrapped in objects as well (which need to be created).
Many LINQ operators call the GetEnumerator method on an collection to iterate it. Calling GetEnumerator usually ensures the creation of yet another object.
Iterating the collection is done using the IEnumerator interface. Interface calls are a bit slower than normal method calls.
IEnumerator objects often need to be disposed or at least, Dispose has to be called.
When performance is a concern, also try using for over foreach.
Again, I love LINQ and I can't remember ever decided not to use a LINQ (to objects) query because of performance. So, don't do any premature optimizations. Start with the most readability solution first, than optimize when needed. So profile, profile and profile.
One thing we identified to be performance problematic is creating lots of lambdas and iterating over small collections. What happens in the converted sample?
Ninjas.FirstOrDefault(ninja => ninja.Id == ninjaId)
First, new instance of (generated) closure type is created. New instance in managed heap, some work for GC.
Second, new delegate instance is created from method in that closure.
Then method FirstOrDefault is called. What it does?
It iterates collection (same as your original code) and calls delegate.
So basically, you have 4 things added here:
1. Create closure
2. Create delegate
3. Call through delegate
4. Collect closure and delegate
If you call FindNinjaById lots of times, you will add this to may be important perforamnce hit. Of course, measure it.
If you replace it with (equivalent)
Ninjas.Where(ninja => ninja.Id == ninjaId).FirstOrDefault()
it adds
5. Creating state machine for iterator ("Where" is yielding function)
Profile
The only way to know for sure is to profile. Yes, certain queries can be slower. But when you look at what ReSharper has replaced here, it's essentially the same thing, done in a different manner. The ninjas are looped, each Id is checked. If anything, you could argue this refactoring comes down to readability. Which of the two do you find easier to read?
Larger data sets will have a bigger impact sure, but as I've said, profile. It's the only way to be sure if such enhancements have a negative effect.
We've built massive apps, with LINQ sprinkled liberally throughout. It's never, ever slowed us down.
It's perfectly possible to write LINQ queries that will be very slow, but it's easier to fix simple LINQ statements than enormous for/if/for/return algorithms.
Take resharper's advice :)
An anecdote: when I was just getting to know C# 3.0 and LINQ, I was still in my "when you have a hammer, everything looks like a nail" phase. As a school assignment, I was supposed to write a connect four/four in row game as an exercise in adversarial search algorithms. I used LINQ throughout the program. In one particular case, I needed to find the row a game-piece would land on if I dropped it in a particular column. Perfect use-case for a LINQ query! This turned out to be really slow. However, LINQ wasn't the problem, the problem was that I was searching to begin with. I optimized this by just keeping a look-up table: an integer array containing the row number for every column of the game-board, updating that table when inserting a game-piece. Needless to say, this was much, much faster.
Lesson learned: optimize your algorithm first, and high level constructs like LINQ might actually make that easier.
That said, there is a definite cost to creating all those delegates. On the other hand, there can also be a performance benefit by utilizing LINQ's lazy nature. If you manually loop over a collection, you're pretty much forced to create intermediate List<>'s whereas with LINQ, you basically stream the results.
The above does the exact same thing.
As long as you use your LINQ queries correctly you will not suffer from performance issues. If you use it correctly it is more likely to be faster due to the skill of the people creating LINQ.
The only thing you can benefit of creating your own is if you want full control or LINQ does not offer what you need or you want a better ability to debug.
The cool thing about LINQ queries is that it makes it dead simple to convert to a parallel query. Depending on what you're doing, it may or may not be faster (as always, profile), but it's pretty neat, nonetheless.
To add my own experience of using LINQ where performance really does matter - with Monotouch - the difference there is still insignificant.
You're 'handicapped' on the 3GS iPhone to around 46mb of ram and a 620mhz ARM processor. Admittedly the code is AOT compiled but even on the simulator where it is JIT'd and going through a long series of indirection the difference is tenths of a millisecond for sets of 1000s of objects.
Along with Windows Mobile this is where you have to worry about the performance costs - not in huge ASP.NET applications that are running on quad-core 8gb servers, or desktops with dual scores. One exception to this would be with large object sets, although arguably you would lazy load anyway, and the initial query task would be performed on the database server.
It's a bit of a cliché on Stackoverflow, but use the shorter more readable code until 100s of milliseconds really do matter.
Related
I needed to access the asymptotic time and space complexity of the IEnumerable.Distinct in big O notation
So I was looking at the implementation of extension method Enumerable.Distinct and I see it is implemented using and internal class Set<T>, which is almost a classical implementation of a hash table with "open addressing"
What quickly catches the eye is that a lot of code in Set<T> is just a copy-paste from HashSet<T>, with some omissions
However, this simplified Set<T> implementation has some obvious flaws, for example the Resize method not using prime numbers for the size of the slots, like HashSet<T> does, see HashHelpers.ExpandPrime
So, my questions are:
What is the reason for code duplication here, why not stick with DRY principle? Especially given the fact that both of these classes are in the same assembly System.Core
It looks like HashSet<T> will perform better, so should I avoid using Distinct extension method, and write my own extension method that would use HashSet<T> instead of Set<T>?
which is almost a classical implementation of a hash table with "open addressing"
Look again. It's separate chaining with list head cells. While the slots are all in an array, finding the next slot in the case of collision is done by examining the next field of the current slot. This has better cache efficiency than using linked lists with each node as a separate heap object, though not as good as open addressing in that regard. At the same time, it avoids some of the cases where open addressing does poorly.
a lot of code in Set is just a copy-paste from HashSet, with some omissions
AFAICT the reason a private implementation of a hash-set was used is that Enumerable and HashSet were developed independently at about the same time. That's just conjecture on my part, but they were both introduced with .NET 3.5 so it's feasible.
It's quite possible that HashSet<T> started by copying Set<T> and then making it better serve being exposed publicly, though it's also possible that the two were both based on the same principle of separate chaining with list head cells
In terms of performance, HashSet's using prime numbers means its more likely to avoid collisions with poor hashes (but just how much an advantage that is, is not a simple question), but Set is lighter in a lot of ways, especially in .NET Core where some things it doesn't need were removed. In particular, that version of Set takes advantage of the fact that once an item is removed (which happens, for example, during Intersect) there will never be an item added, which allows it to leave out freelist and any work related to it, which HashSet couldn't do. Even the initial implementation is lighter in not tracking a version to catch changes during enumeration, which is a small cost, but a cost to every addition and removal nevertheless.
As such, with different sets of data with different distributions of hash codes sometimes one performs better, sometimes the other.
Especially given the fact that both of these classes are in the same assembly System.Core
Only in some versions of .NET, in some they're in separate assemblies. In .NET Core we had two versions of Set<T>, one in the assembly that has System.Linq and one in the separate assembly that has System.Linq.Expressions. The former got trimmed down as described above, the latter replaced with a use of HashSet<T> as it was doing less there.
Of course System.Core came first, but the fact that those elements could be separated out at all speaks of System.Core not being a single monolithic blob of inter-dependencies.
That there is now a ToHashSet() method in .NET Core's version of Linq makes the possibility of replacing Set<T> with HashSet<T> more justifiable, though not a no-brainer. I think #james-ko was considering testing the benefits of doing that.
It looks like HashSet<T> will perform better
For the reasons explained above, that might not be the case, though it might indeed, depending on source data. That's before getting into considerations of optimisations that go across a few different linq methods (not many in the initial versions of linq, but a good few in .NET Core).
so should I avoid using Distinct extension method, and write my own extension method that would use HashSet<T> instead of Set<T>.
Use Distinct(). If you've a bottle neck then it might be that HashSet<T> will win with a given data-set, but if you do try that make sure your profiling closely matches real values your code will encounter in real life. There's no point deciding one approach is the faster based on some arbitrary tests if your application hits cases where the other does better. (And if I was finding this a problem spot, I'd take a look at whether the GetHashCode() of the types in question could be improved for either speed or distribution of bits, first).
Do closures in c# cause code bloat in the generated il? I was told to avoid lambdas with closure variables as they generate hidden classes in the object file that can store the context for the lambda. A class for every lambda with the closed over variables. Is this true? Or does the compiler reuse an existing class, like Tuple or some internal class?
Extra classes are only generated when they need to be - when you capture variables other than this. However, this isn't really code bloat in most cases - it's necessary in order to make the delegate work the way you need it to.
In some cases you could write more efficient code yourself, but usually to get a delegate with the same effect, you'd end up writing code which was similar to what the compiler would generate for you... but considerably harder to read.
Most of the time you shouldn't worry about this sort of "bloat" - avoid micro-optimizing for performance to start with - optimize for readability, and measure the performance instead of guessing about it. Then you can attack the bits of code which really matter, and maybe sacrifice a bit of readability for performance there, when you've proved that it's worth it.
(Writing modern C# and deliberately avoiding lambda expressions is like trying to code with one hand tied behind your back. If the person advising you is worried about the "bloat" of closures, you could probably give him a heart attack by showing him the state machine generated for async/await in C# 5...)
Yes, this is true.
A class that keeps track of the variable needs to exist. A Tuple or internal class would not be able to do this for all possible code paths, so such a state machine needs to be generated in IL specifically for each lambda/closure.
Whether this is a problem for your application or not is something for you to determine.
If I have a class with some value member that I want to store regardless of type, I would think that an object type would be the best. Lets say that the object can realistically be one of three types: string, int, customeClass. Would it be better to keep an extra enum member of the class with what type is stored in the value? Or is the execution of
if(object is string){...}
else if(object is int){...}
else if(object is customeClass){...}
fast enough that it's not worth storing the extra information?
Don't do premature optimization before measuring and proving that is operator is a local bottleneck on a hot code path. Maintaining the enum for the alternative approach will tax development over long time.
With all respect...I think this is called premature optimization. I wouldn't worry about the speed of an If statement even if it is a loop of 10k+ iterations.
The performance of the IS test in .NET is rarely a performance problem - worst case is when the result is False and the object has a deep inheritance hierarchy. IS will have to perform multiple lookups going up the object's inheritance chain.
Unless your objects all have deep (100+) inheritance, the performance difference will be negligible.
The biggest difference between testing inheritance and testing an enum is that you can test an enum against multiple values in a switch statement. IS tests always require an if statement chain. The larger (> 10?) the number of elements to test, the greater the performance advantage of switch statements over if statements.
Creating a design where testing the type of the object is a key element of the design seems highly questionable. You should be trying to use polymorphism to allow you to manipulate various types without needing to know the type of each object. A virtual method call will be faster than testing inheritance or testing enums when the number of types involved is greater than 1.
This code will execute as fast as a cast (in other words it will be very fast as it is a single IL instruction). Retrieving an enum value from a property involves a lot more work (items must be pushed and popped from the stack and methods must be called) which would make it much slower than using is.
All that being said, however, you shouldn't be concerning yourself with performance at this level until you have identified that this code is introducing performance issues. For most purposes this kind of optimization produces almost no measurable performance difference.
That will be fast enough. Storing any extra data would be uncessary as you'd have to lookup the properties of the instance of the class to get the type that you stored anyway if you did.
It is fast enough, it seems that you are doing a premature optimization which you shouldn't unless you've identified this as a bottleneck for your application performance.
I will be creating a project that will use dictionary lookups and inserts quite a bit. Is this something to be concerned about?
Also, if I do benchmarking and such and it is really bad, then what is the best way of replacing dictionary with something else? Would using an array with "hashed" keys even be faster? That wouldn't help on insert time though will it?
Also, I don't think I'm micro-optimizing because this really will be a significant part of code on a production server, so if this takes an extra 100ms to complete, then we will be looking for new ways to handle this.
You are micro-optimizing. Do you even have working code yet? Remember, "If it doesn't work, it doesn't matter how fast it doesn't work." (Mich Ravera) http://www.codingninja.co.uk/best-programmers-quotes/.
You have no idea where the bottlenecks will be, and already you're focused on Dictionary. What if the problem is somewhere else?
How do you know how the Dictionary class is implemented? Maybe it already uses an array with hashed keys!
P.S. It's really ".NET Dictionaries", not "C# Dictionaries", because C# is just one of several programming languages that use the framework.
Hello, I will be creating a project
that will use dictionary lookups and
inserts quite a bit. Is this something
to be concerned about?
Yes. It is always wise to consider performance factors up front.
The form that your concern should take is as follows: your concern should be encouraging you to write realistic, user-focused performance specifications. It should be encouraging you to start writing performance tests early, and running them often, so that you can see how every single change to the product affects performance. That way you will be informed immediately when a code change causes a user-affecting change in performance. And it should be encouraging you to run profiles often, so that you are reasoning about performance based on empirical measurements, rather than random guesses and hunches.
Also, if I do benchmarking and such
and it is really bad, then what is the
best way of replacing dictionary with
something else?
The best way to do this is to build a reasonable abstraction layer. If you have a class (or interface) which represents the "insert" and "lookup" abstract data type, then you can replace its internals without changing any of the callers.
Note that adding a layer of abstraction itself has a performance cost. If your profiling shows that the abstraction layer is too expensive, if the extra couple nanoseconds per call is too much, then you might have to get rid of the abstraction layer. Again, this decision will be driven by real-world performance data.
Would using an array with "hashed"
keys even be faster? That wouldn't
help on insert time though will it?
Neither you nor anyone reading this can possibly know which one is faster until you write it both ways and then benchmark it both ways under real-world conditions. Doing it under "lab" conditions will skew your results; you'll need to understand how things work when the GC is under realistic memory pressure, and so on. You might as well ask us which horse will run faster in next year's Kentucky Derby. If we knew the answer just by looking at the racing form, we'd all be rich already. You can't possibly expect anyone to know which of two entirely hypothetical, unwritten pieces of code will be faster under unspecified conditions!
The Dictionary<TKey, TValue> class is actually implemented as a hash table which makes lookups very fast (close to O(1)). See the API documentation for more information. I doubt you could make a better implementation yourself.
Wait and see if the performance of your application is below expectations
If it is then use a profiler to determine if the Dictionary lookup is the source of the problem
If it is then do some tests with representative data to see if another choice of list would be quicker.
In short - no, in general you shouldn't worry about the performance of implementation details until after you have a problem.
I would do a benchmark of the Dictionary, HashTable (HashSet in .NET), and perhaps a home grown class, and see which works out best under your typical usage conditions.
Normally I would say it's fine (insert StackOverflow's favorite premature ejaculation quote here), but if this is a core peice of the application, Benchmark, Benchmark, Benchmark.
The only concern that I can think of is that the speed of the dictionary relies on the key class having a reasonably fast GetHashCode method. Lookups and inserts are really fast, so you shouldn't have any problem there.
Regarding using an array, that's what the Dictionary class does already. Actually it uses two arrays, one for the keys and one for the values.
If you would have any performance problems with a Dictionary, it would be quite easy to make a wrapper for any kind of storage, that has the same methods and behaviour as a Dictionary so that you can replace it seamlessly.
I'm not sure that anyone has really answered this part yet:
Also, if I do benchmarking and such
and it is really bad, then what is the
best way of replacing dictionary with
something else?
For this, wherever possible, declare your variables as IDictionary<TKey, TValue>. That's the main interface that Dictionary derives from. (I'm assuming that if you care that much about performance, then you aren't considering non-generic collections.) Then, in the future, you can change the underlying implementation class without having to change any of the code that uses that dictionary. For example:
IDictionary<string, int> myDict = new Dictionary<string, int>();
If your application is multithreaded then the key part of performance is going to be synchronizing this Dictionary correctly.
If it is single-threaded then almost certainly bottleneck will be elsewhere. Such as reading these objects from wherever you are reading them.
I use Dictionary for UDP relay server . Each time packet arrives it performs Dictionary.ContainsKey and Dictionary[Key] , and it works great (massive number of clients). I had concerns when I was making the thing but it turned out that was last thing I should worry about.
Have a look at C# HybridDictionary Usage
HybridDictionary Class
This class is recommended for cases
where the number of elements in a
dictionary is unknown. It takes
advantage of the improved performance
of a ListDictionary with small
collections, and offers the
flexibility of switching to a
Hashtable which handles larger
collections better than ListDictionary
You may consider using the C5 library. I've found it to be very fast and thoughtfully designed. Others on stackoverflow have found the same. With C5 you have the option of using general type interfaces (with a captial I), or directly the data structures underneath. Naturally the interfaces allow you to swap out different implementations, but I have found in performance testing that the interfaces will cost you.
You may want to look at the KeyedCollection class in System.ObjectModel. From the MSDN description, "provides the abstract base class for a collection whose keys are embedded in the values."
The system I work on here was written before .net 2.0 and didn't have the benefit of generics. It was eventually updated to 2.0, but none of the code was refactored due to time constraints. There are a number of places where the code uses ArraysLists etc. that store things as objects.
From performance perspective, how important change the code to using generics? I know from a perfomance perspective, boxing and unboxing etc., it is inefficient, but how much of a performance gain will there really be from changing it? Are generics something to use on a go forward basis, or it there enough of a performance change that a conscience effort should be made to update old code?
Technically the performance of generics is, as you say, better. However, unless performance is hugely important AND you've already optimised in other areas you're likely to get MUCH better improvements by spending your time elsewhere.
I would suggest:
use generics going forward.
if you have solid unit tests then refactor to generics as you touch code
spend other time doing refactorings/measurement that will significantly improve performance (database calls, changing data structures, etc) rather than a few milliseconds here and there.
Of course there's reasons other than performance to change to generics:
less error prone, since you have compile-time checking of types
more readable, you don't need to cast all over the place and it's obvious what type is stored in a collection
if you're using generics going forward, then it's cleaner to use them everywhere
Here's the results I got from a simple parsing of a string from a 100KB file 100,000 times. The Generic List(Of char) took 612.293 seconds to go 100,000 times through the file.
The ArrayList took 2,880.415 seconds to go 100,000 times through the file. This means in this scenario (as your mileage will vary) the Generic List(Of char) is 4.7 times faster.
Here is the code I ran through 100,000 times:
Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run
Dim genList As New ArrayList
For Each ch As Char In strToProcess.ToCharArray
genList.Add(ch)
Next
Dim dummy As New System.Text.StringBuilder()
For i As Integer = 0 To genList.Count - 1
dummy.Append(genList(i))
Next
End Sub
Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run
Dim genList As New List(Of Char)
For Each ch As Char In strToProcess.ToCharArray
genList.Add(ch)
Next
Dim dummy As New System.Text.StringBuilder()
For i As Integer = 0 To genList.Count - 1
dummy.Append(genList(i))
Next
End Sub
The only way to know for sure is to profile your code using a tool like dotTrace.
http://www.jetbrains.com/profiler/
It's possible that the boxing/unboxing is trivial in your particular application and wouldn't be worth refactoring. Going forward, you should still consider using generics due to the compile-time type safety.
Generics, whether Java or .NET, should be used for design and type safety, not for performance. Autoboxing is different from generics (essentially implicit object to primitive conversions), and as you mentioned, you should NOT use them in place of a primitive if there is to be a lot of arithmetic or other operations which will cause a performance hit from the repeated implicit object creation/destruction.
Overall I would suggest using going forward, and only updating existing code if it needs to be cleaned up for type safety / design purposes, not performance.
It depends, the best answer is to profile your code and see. I like AQTime but a number of packages exist for this.
In general, if an ArrayList is being used a LOT it may be worth switching it to a generic version. Really though, it's most likely that you wouldn't even be able to measure the performance difference. Boxing and unboxing are extra steps but modern computers are so fast that it makes almost no difference. As an ArrayList is really just an normal array with a nice wrapper, you would probably see much more performance gained from better data structure selection (ArrayList.Remove is O(n)!) than with the conversion to generics.
Edit: Outlaw Programmer has a good point, you will still be boxing and unboxing with generics, it just happens implicitly. All the code around checking for exceptions and nulls from casting and "is/as" keywords would help a bit though.
The biggest gains, you will find in Maintenance phases. Generics are much easier to deal with and update, without having to deal with conversion and casting issues. If this is code that you continually visit, then by all means take the effort. If this is code that hasn't been touched in years, I wouldn't really bother.
What does autoboxing/unboxing have to do with generics? This is just a type-safety issue. With a non-generic collection, you are required to explicitly cast back to an object's actual type. With generics, you can skip this step. I don't think there is a performance difference one way or the other.
My old company actually considered this problem. The approach we took was: if it's easy to refactor, do it; if not (i.e. it will touch too many classes), leave it for a later time. It really depends on whether or not you have the time to do it, or whether there are more important items to be coding (i.e. features you should be implementing for clients).
Then again, if you're not working on something for a client, go ahead and spend time refactoring. It'll improve readability of the code for yourself.
Depends on how much is out there in your code. If you binding or display large lists in the UI, you would probably see a great gain in performance.
If your ArrayList are just sprinkled about here and there, then it probably wouldn't be a big deal to just get it cleaned up, but also wouldn't impact overall performance very much.
If you are using a lot a ArrayLists throughout your code and it would be a big untertaking to replace them (something that may impact your schedules), then you could adopt a if-you-touch-it-change-it approach.
Main thing is, though, that Generics are a lot easier to read, and are more stable across the app due to the strong typing you get from them. You'll see gains not just from performance, but from code maintainablity and stability. If you can do it quickly, I'd say do it.
If you can get buy-in from the Product Owner, I'd recommend getting it cleaned up. You love your code more afterward.
If the entities in the ArrayLists are Object types, you'll gain a little from not casting them to the correct type. If they're Value types (structs or primitives like Int32), then the boxing/unboxing process adds a lot of overhead, and Generic collections should be much faster.
Here's an MSDN article on the subject
Generics has much better performance especially if you'll be using value-type (int, bool, struct etc.) where you'll gain a noticeble performance gain.
Using Arraylist with value-types causes boxing/unboxing which if done several hundred times is substantialy slower then using generic List.
when storing value-types as object you'll up to four time memory per item. While this amount won't drain your RAM the cache memory that is smaller could contain less items, Which means that while iterating a long collections there would be many copies from the main memory to the cache that would slow your application.
I wrote about here.
Using generics should also mean that your code will be simplier and easy to use if you want to leverage things like linq in the later c# versions.