If .Count or .Count() is used several times on objects that implement ICollection (therefore with O(1) computational complexity, unless of course it has been overriden), is it better performance-wise (not memory wise), ev开发者_运维知识库en for a very small difference, to cache the value in a temporary variable rather than accessing the property value each time it is needed?
Yes, it could be (very slightly) faster, since the overhead of a method call, associated error checking, and (in the case of Count()) the dynamic type checking for ICollection have some amount of overhead.
Is it worth it though? That's entirely up to you and your application. If you're in a very tight inner loop, it might be worth it. Then again, on more recent .NET runtimes, this sort of trivial property will probably get inlined in such circumstances.
As always, let your profiler tell you where the hotspots are in your application.
Answering the question directly, even an O(1) operation can take a long time to complete; it's just that it always takes the same time no matter how big the collection. Caching the result and reading it back is going to be fast, always, but not guaranteed to be faster than any given O(1) operation. You need some timings first ;)
Sorry, it's a mistake to think that ICollection.Count
is O(1)
. It morally should be, but there's no guarantee that it is:
public EvilCollection<T> : ICollection<T> {
private readonly ICollection<T> collection;
private readonly Func<int, int> slowGrowingFunction;
public EvilCollection(
ICollection<T> collection,
Func<int, int> slowGrowingFunction)
{
this.collection = collection;
this.slowGrowingFunction = slowGrowingFunction;
}
public int Count {
get {
Thread.Sleep(1000 * this.slowGrowingFunction(this.collection.Count));
return this.collection.Count;
}
}
// other methods wrap methods on collection for ICollection<T>
}
ICollection<T> evilCollection =
new EvilCollection<T>(collection, n => Ackermann(4, n));
Oh no, evilCollection.Count
is O(Ackermann(4, n))
!
That said, I wouldn't worry about this unless I knew I might be getting in evil collections, and I found it to be a significant performance bottleneck. Keep in mind, the code is less clear, it could be less correct (what is the count updates after you've cached the result?), etc.
Just write the simplest code that works (use ICollection<T>.Count
). If and only if it's a performance bottleneck in your application would I worry about tuning it.
No, there's no need; there's no benefit to using a temporary variable. Additionally, if you're caching your count, you run the risk of the count being incorrect if the collection set changes.
The answer is NO if you are sure what .Count()
will be doing now and in the feature. The answer is YES if .Count()
is some implementation that may change. Let's say you change the implementation with some LinkedList which may not be O(1).
精彩评论