首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Interlocked.Read / Interlocked.Exchange在Mono上比.NET慢得多?

Interlocked.Read / Interlocked.Exchange在Mono上比.NET慢得多?
EN

Stack Overflow用户
提问于 2012-02-07 15:57:52
回答 1查看 1.1K关注 0票数 3

很抱歉提出了一个很长的问题,但是有一个Jon引用,所以这对一些人来说可能是值得的。

简而言之::

在Mono框架中运行Interlocked.Read / Interlocked.Exchange似乎要比在.NET框架中运行时慢得多。我很想知道为什么。

In long:

我想要一个32位平台的线程安全的双面,所以我做了这个结构:

代码语言:javascript
复制
public interface IThreadSafeDouble
{
    double Value { get; set; }
}

public struct LockedThreadSafeDouble : IThreadSafeDouble
{
    private readonly object Locker;
    private double _Value;

    public double Value
    {
        get { lock (Locker) return _Value; }
        set { lock (Locker) _Value = value; }
    }

    public LockedThreadSafeDouble(object init)
        : this()
    {
        Locker = new object();
    }
}

然后我读了Jon对this question的回答,所以我创建了这个结构:

代码语言:javascript
复制
public struct InterlockedThreadSafeDouble : IThreadSafeDouble
{
    private long _Value;

    public double Value
    {
        get { return BitConverter.Int64BitsToDouble(Interlocked.Read(ref _Value)); }
        set { Interlocked.Exchange(ref _Value, BitConverter.DoubleToInt64Bits(value)); }
    }
}

然后我写了这个测试:

代码语言:javascript
复制
    private static TimeSpan ThreadSafeDoubleTest2(IThreadSafeDouble dbl)
    {
        var incrementTarg = 10000000;
        var sw = new Stopwatch();
        sw.Start();
        for (var i = 0; i < incrementTarg; i++, dbl.Value++);
        sw.Stop();
        return sw.Elapsed;
    }

    private static void ThreadSafeTest()
    {
        var interlockedDbl = new InterlockedThreadSafeDouble();
        var interlockedTim = ThreadSafeDoubleTest2(interlockedDbl);

        var lockedDbl = new LockedThreadSafeDouble(true);
        var lockedTim = ThreadSafeDoubleTest2(lockedDbl);

        System.Console.WriteLine("Interlocked Time: " + interlockedTim);
        System.Console.WriteLine("Locked Time:      " + lockedTim);
    }       

    public static void Main(string[] args)
    {
        for (var i = 0; i < 5; i++)
        {
            System.Console.WriteLine("Test #" + (i + 1));
            ThreadSafeTest();
        }
        System.Console.WriteLine("Done testing.");
        System.Console.ReadLine();
    }

我使用.NET框架获得了这个结果:

这个结果使用Mono框架:

我在同一台机器(Windows )上运行了两次测试,测试结果是一致的。我很想知道为什么Interlocked.Read/Interlocked.Exchange在Mono框架上的执行速度似乎要慢得多。

更新:

我编写了以下简单的测试:

代码语言:javascript
复制
long val = 1;
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < 100000000; i++) {
    Interlocked.Exchange(ref val, 2);
    // Interlocked.Read(ref val);
}
sw.Stop();
System.Console.WriteLine("Time: " + sw.Elapsed);

.NET框架始终使用ExchangeRead返回~2.5秒。Mono框架返回~5.1秒。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-02-08 21:50:08

得出性能结论并不容易。在第一个例子中,long<->双转换可能是重要的因素。通过将所有双倍更改为longs (并删除转换),这是我在Windows中使用32位Mono的时候:

代码语言:javascript
复制
Test #1
Interlocked Time: 00:00:01.2548628
Locked Time:      00:00:01.7281594
Test #2
Interlocked Time: 00:00:01.2466018
Locked Time:      00:00:01.7219013
Test #3
Interlocked Time: 00:00:01.2590181
Locked Time:      00:00:01.7443508
Test #4
Interlocked Time: 00:00:01.2575325
Locked Time:      00:00:01.7309012
Test #5
Interlocked Time: 00:00:01.2593490
Locked Time:      00:00:01.7528010
Done testing.

因此,互锁的实现并不是这里最大的因素。

但是接下来是第二个没有转换的例子。为什么会这样?我认为答案是循环展开,在.NET JIT编译器中做得更好。但这只是猜测。如果要比较现实场景中的互锁性能,可以(至少)有两个选项:

在实际的scenario.

  • Compare中,JIT编译器发出的机器代码
  1. 对它们进行了比较,并查看了互锁.

的确切实现。

还请注意,上述实现提供的唯一保证是您不会观察到撕裂。例如,它没有给您(通常需要的)保证,如果两个线程正在递增值,之和将是正确的(也就是说,它将考虑所有的增量)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9179461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档