【发布时间】:2012-02-07 15:57:52
【问题描述】:
抱歉这个问题太长了,但是有 Jon Skeet 的参考资料,所以对某些人来说可能是值得的。
简而言之:Interlocked.Read / Interlocked.Exchange 在 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 框架得到了这个结果:
使用 Mono 框架的结果如下:
我在同一台机器 (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);
.NET 框架在 Exchange 和 Read 上始终返回 ~2.5 秒。 Mono 框架返回 ~5.1 秒。
【问题讨论】:
-
我会从“这个测试并不是真的有用”开始:在 Windows 上运行 .Net 4.0 64bit 并在 Linux 上运行 Mono 来比较当前版本的性能。
-
你实际上不知道是不是Interlocked方法更慢,也可能是接口调度。我建议在得出任何结论之前尽可能多地去除概括(即,只需将 Interlocked 方法放在循环中)。
-
@RolfBjarneKvinge -- 我用更简单的测试和结果更新了我的问题。
-
只是为了确保:您使用的是发布版本,并且您没有附加调试器?
-
您的新测试基本上确认您的原始测试速度较慢,主要是由于其他因素而不是 Interlocked。它证实了每个实例的真正差异几乎没有。
标签: .net performance mono thread-safety interlocked