当操作是O(1)时,是否值得缓存.Count(或.Count())的结果?

时间:2011-07-22 17:21:08

标签: c# .net performance count

如果.Count或.Count()在实现ICollection的对象上多次使用(因此具有O(1)计算复杂度,除非它已被覆盖),它是否在性能方面更好(不是内存方式) ,即使是一个非常小的差异,要将值缓存在临时变量中,而不是每次需要时访问属性值?

5 个答案:

答案 0 :(得分:3)

是的,它可能(非常轻微)更快,因为方法调用的开销,相关的错误检查和(在Count()的情况下)ICollection的动态类型检查有一些开销。

虽然值得吗?这完全取决于您和您的应用程序。如果你处于一个非常紧密的内循环中,它可能是值得的。然后,在最近的.NET运行时,这种琐碎的属性可能会在这种情况下被内联。

与往常一样,让您的探查器告诉您应用程序中的热点位置。

答案 1 :(得分:3)

直接回答问题,即使是O(1)操作也需要很长时间才能完成;只是无论收集多大,它总是需要相同的时间。缓存结果并将其读回将会很快,但不能保证比任何给定的O(1)操作更快。你首先需要一些时间;)

答案 2 :(得分:2)

抱歉,我认为ICollection.CountO(1)是错误的。它在道德上应该是,但不能保证它是:

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));

哦不,evilCollection.CountO(Ackermann(4, n))

那就是说,我不会担心这个,除非我知道我可能会收到邪恶的收藏品,我发现这是一个重大的性能瓶颈。请记住,代码少了清楚,它可能不太正确(缓存结果后的计数更新是什么?)等。

只需编写最简单的代码(使用ICollection<T>.Count)。当且仅当它是您应用程序中的性能瓶颈时,我会担心调整它。

答案 3 :(得分:0)

不,没有必要;使用临时变量没有任何好处。此外,如果您正在缓存计数,那么如果收集集发生变化,您将面临计数错误的风险。

答案 4 :(得分:0)

如果您确定.Count()现在和该功能中将要执行的操作,则答案为。答案是如果.Count()是某些可能发生变化的实施。假设你用一些可能不是O(1)的LinkedList来改变实现。

相关问题