Interlocked.Increment的性能

时间:2009-06-23 17:46:46

标签: .net performance interlocked interlocked-increment

Interlocked.Increment(ref x)对于各种平台上的整数和长期,是否比x++更快或更慢?

6 个答案:

答案 0 :(得分:40)

它的速度较慢,因为它强制动作以原子方式发生,并且它充当内存屏障,从而消除了处理器重新排序指令周围内存访问的能力。

当您希望操作在线程之间可以共享的状态时,您应该使用Interlocked.Increment - 它并不是x ++的完全替代。

答案 1 :(得分:16)

根据我们的经验,Windows上的InterlockedIncrement()等是非常重要的影响。在一个示例中,我们能够消除互锁并使用++ / - 代替。仅此一项就将运行时间从140秒减少到110秒。我的分析是,互锁会强制进行内存往返(否则其他内核怎么能看到它?)。 L1高速缓存读/写大约是10个时钟周期,但存储器读/写更像是100。

在此示例中,我估计增量/减量操作的数量约为10亿。因此在2Ghz CPU上,这对于++ / - 来说是5秒,对于互锁则是50秒。在几个线程之间传播差异,并且接近30秒。

答案 2 :(得分:6)

考虑一下,你会发现Increment调用不能比增量运算符的简单应用更快。如果是,则编译器的增量运算符的实现将在内部调用Increment,并且它们执行相同的操作。

但是,正如您自己测试它所看到的那样,它们的表现并不相同。

这两个选项有不同的用途。一般使用增量运算符。当您需要将操作设置为原子操作时,请使用Increment,并确保该变量的所有其他用户也使用互锁操作。 (如果他们不是全部合作,那么它并没有真正的帮助。)

答案 3 :(得分:4)

速度慢了。但是,对于在标量变量上实现线程安全性,它是我所知道的最高效的通用方法。

答案 4 :(得分:3)

它总是会变慢,因为它必须执行CPU总线锁定而不仅仅是更新寄存器。然而,现代CPU实现接近寄存器性能,因此即使在实时处理中它也可以忽略不计。

答案 5 :(得分:3)

我的性能测试:

波动性:65,174,400

锁定:62,428,600

联锁:113,248,900

TimeSpan span = TimeSpan.FromSeconds(5);

object syncRoot = new object();
long test = long.MinValue;

Do(span, "volatile", () => {

    long r = Thread.VolatileRead(ref test);

    r++;

    Thread.VolatileWrite(ref test, r);
});

Do(span, "lock", () =>
{
    lock (syncRoot)
    {
        test++;
    }
});

Do(span, "interlocked", () =>
{
    Interlocked.Increment(ref test);
});