互锁调试与发布模式下的增量与锁定 [英] Interlocked.Increment vs lock in debug vs release mode

查看:122
本文介绍了互锁调试与发布模式下的增量与锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试Interlocked.Incrementlock在计算机体系结构上的行为,因为我在

I was testing how Interlocked.Increment and lock behave on my computer's architecture because I read the following lines in this article.

正如用Interlocked.Increment重写的那样,该方法至少在某些体系结构上应该执行得更快.

As rewritten with Interlocked.Increment, the method should execute faster, at least on some architectures.

使用以下代码,我深信值得检查项目中的锁.

Using the following code I get convinced that it's worth to review locks in my projects.

var watch = new Stopwatch();
var locker = new object();
int counter = 0;

watch.Start();
for (int i = 0; i < 100000000; i++)
{
    lock (locker)
    {
        counter++;
    }
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);

watch.Reset();
counter = 0;

watch.Start();
for (int i = 0; i < 100000000; i++)
{
    Interlocked.Increment(ref counter);
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);

我获得了稳定的结果,锁定的近似值为 2.4s ,互锁的近似值为 1.2s .但是,令我惊讶的是,发现在释放模式下运行此代码只会将Interlocked的值提高到大约 0.7s ,并且锁定时间保持不变.这是为什么?在释放模式下未锁定时,如何优化互锁?

I'm getting stable results with approximate values 2.4s for locking and 1.2s for Interlocked. However I was surprised to discover that running this code in release mode improves value only for Interlocked to approximately 0.7s and the locking time remains the same. Why is that? How is Interlocked optimized when in release mode that lock is not?

推荐答案

您必须查看生成的机器代码才能看到其中的区别,即Debug + Windows + Disassembly. Interlocked.Increment()调用的调试版本:

You have to look at the generated machine code to see the difference, Debug + Windows + Disassembly. The debug build version of the Interlocked.Increment() call:

   00FC27AD  call        7327A810 

发行版本:

   025F279D  lock inc    dword ptr [ebp-24h] 

换句话说,抖动优化器在Release版本中变得非常聪明,并将对辅助函数的调用替换为单个机器指令.

Or in other words, the jitter optimizer got really smart in the Release build and replaced a call to a helper function into a single machine instruction.

优化并没有比这更好.不能对 lock 语句下面的Monitor.Enter()方法调用应用相同的优化,这是CLR中实现的相当重要的函数,不能被内联.除了Interlocked.Increment()之外,它还执行许多其他操作,当线程阻止尝试获取监视器并维护等待线程的队列时,它允许操作系统重新调度.这对于确保良好的并发性非常重要,只是在测试代码中没有,因为锁是完全没有争议的.提防那些不能近似实际使用的综合基准.

Optimization just doesn't get better than that. The same optimization cannot be applied to the Monitor.Enter() method call that's underneath the lock statement, it is a pretty substantial function that's implemented in the CLR and cannot be inlined. It does many things beyond Interlocked.Increment(), it allows the operating system to reschedule when a thread blocks on trying to acquire the monitor and maintains a queue of waiting threads. That can be pretty important to ensure good concurrency, just not in your test code since the lock is entirely uncontested. Beware of synthetic benchmarks that don't approximate actual usage.

这篇关于互锁调试与发布模式下的增量与锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆