gpt4 book ai didi

.net - Interlocked.Read/Interlocked.Exchange 在 Mono 上比 .NET 慢很多吗?

转载 作者:行者123 更新时间:2023-12-02 02:19:01 26 4
gpt4 key购买 nike

很抱歉问了这么长的问题,但是有 Jon Skeet 的引用资料,所以对某些人来说可能是值得的。

简而言之:
Interlocked.Read/Interlocked.Exchange 在 Mono 框架中运行时的执行速度似乎比 Mono 框架慢得多在 .NET 框架中运行时。我很想知道为什么。

长:
我想要 32 位平台的线程安全 double ,所以我制作了这个结构:

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 Skeet 对 this question 的回答,所以我做了这个结构:

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

然后我写了这个测试:

    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 框架得到了这个结果: .NET Interlocked test results

这个结果使用了 Mono 框架: Mono Interlocked test results

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

更新:

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

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

对于 ExchangeRead,.NET 框架始终返回 ~2.5 秒。 Mono 框架返回 ~5.1 秒。

最佳答案

得出性能结论并非易事。在第一个示例中,long<->double 转换可能是重要因素。通过将所有 double 更改为长整数(并删除转换),这些是我在 Windows 中使用 32 位单声道的时间:

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.

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

但是你有第二个没有转化的例子。为什么会这样?我认为答案是循环展开,在 .NET JIT 编译器中做得更好。但这只是一个猜测。如果你想比较现实生活场景中的联锁性能,你有(至少)两个选择:

  1. 在现实生活场景中比较它们。
  2. 比较 JIT 编译器生成的机器代码,查看 Interlocked 的确切实现。

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

关于.net - Interlocked.Read/Interlocked.Exchange 在 Mono 上比 .NET 慢很多吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9179461/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com