gpt4 book ai didi

c# - 为什么每个人都说 SpinLock 更快?

转载 作者:太空狗 更新时间:2023-10-29 19:49:36 31 4
gpt4 key购买 nike

<分区>

我在互联网上阅读了很多文档、文章和帖子。几乎每个人和任何地方都承认 SpinLock 对于短时间运行的代码片段来说更快,但我做了一个测试,在我看来,简单的 Monitor.Enter 比 SpinLock.Enter 工作得更快(测试是针对 .NET 4.5 编译的)

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Linq;
using System.Globalization;
using System.ComponentModel;
using System.Threading;
using System.Net.Sockets;
using System.Net;

class Program
{
static int _loopsCount = 1000000;
static int _threadsCount = -1;

static ProcessPriorityClass _processPriority = ProcessPriorityClass.RealTime;
static ThreadPriority _threadPriority = ThreadPriority.Highest;

static long _testingVar = 0;


static void Main(string[] args)
{
_threadsCount = Environment.ProcessorCount;

Console.WriteLine("Cores/processors count: {0}", Environment.ProcessorCount);

Process.GetCurrentProcess().PriorityClass = _processPriority;

TimeSpan tsInterlocked = ExecuteInterlocked();
TimeSpan tsSpinLock = ExecuteSpinLock();
TimeSpan tsMonitor = ExecuteMonitor();

Console.WriteLine("Test with interlocked: {0} ms\r\nTest with SpinLock: {1} ms\r\nTest with Monitor: {2} ms",
tsInterlocked.TotalMilliseconds,
tsSpinLock.TotalMilliseconds,
tsMonitor.TotalMilliseconds);

Console.ReadLine();
}

static TimeSpan ExecuteInterlocked()
{
_testingVar = 0;

ManualResetEvent _startEvent = new ManualResetEvent(false);
CountdownEvent _endCountdown = new CountdownEvent(_threadsCount);

Thread[] threads = new Thread[_threadsCount];

for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(() =>
{
_startEvent.WaitOne();

for (int j = 0; j < _loopsCount; j++)
{
Interlocked.Increment(ref _testingVar);
}

_endCountdown.Signal();
});

threads[i].Priority = _threadPriority;
threads[i].Start();
}

Stopwatch sw = Stopwatch.StartNew();

_startEvent.Set();
_endCountdown.Wait();

return sw.Elapsed;
}

static SpinLock _spinLock = new SpinLock();

static TimeSpan ExecuteSpinLock()
{
_testingVar = 0;

ManualResetEvent _startEvent = new ManualResetEvent(false);
CountdownEvent _endCountdown = new CountdownEvent(_threadsCount);

Thread[] threads = new Thread[_threadsCount];

for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(() =>
{
_startEvent.WaitOne();

bool lockTaken;

for (int j = 0; j < _loopsCount; j++)
{
lockTaken = false;

try
{
_spinLock.Enter(ref lockTaken);

_testingVar++;
}
finally
{
if (lockTaken)
{
_spinLock.Exit();
}
}
}

_endCountdown.Signal();
});

threads[i].Priority = _threadPriority;
threads[i].Start();
}

Stopwatch sw = Stopwatch.StartNew();

_startEvent.Set();
_endCountdown.Wait();

return sw.Elapsed;
}

static object _locker = new object();

static TimeSpan ExecuteMonitor()
{
_testingVar = 0;

ManualResetEvent _startEvent = new ManualResetEvent(false);
CountdownEvent _endCountdown = new CountdownEvent(_threadsCount);

Thread[] threads = new Thread[_threadsCount];

for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(() =>
{
_startEvent.WaitOne();

bool lockTaken;

for (int j = 0; j < _loopsCount; j++)
{
lockTaken = false;

try
{
Monitor.Enter(_locker, ref lockTaken);

_testingVar++;
}
finally
{
if (lockTaken)
{
Monitor.Exit(_locker);
}
}
}

_endCountdown.Signal();
});

threads[i].Priority = _threadPriority;
threads[i].Start();
}

Stopwatch sw = Stopwatch.StartNew();

_startEvent.Set();
_endCountdown.Wait();

return sw.Elapsed;
}
}

在具有 24 个 2.5 GHz 内核的服务器上,这个使用 x64 编译的应用程序产生了以下结果:

Cores/processors count: 24
Test with interlocked: 1373.0829 ms
Test with SpinLock: 10894.6283 ms
Test with Monitor: 1171.1591 ms

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