Skip to content

Instantly share code, notes, and snippets.

@kflu
Created July 9, 2014 21:21
Show Gist options
  • Save kflu/f3d1143a206ecdb26079 to your computer and use it in GitHub Desktop.
Save kflu/f3d1143a206ecdb26079 to your computer and use it in GitHub Desktop.
Compares spinlock and regular lock to understand under which circumstances does spinlock provides perf benefit.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication27
{
class SpinLockDemo2
{
static int N = 1000;
static int nTask;
static Queue<Data> _queue = new Queue<Data>();
static object _lock = new Object();
static SpinLock _spinlock = new SpinLock();
const int sleep = 10;
class Data
{
public string Name { get; set; }
public double Number { get; set; }
}
static void Main(string[] args)
{
foreach (int i in new int[] { 5, 10, 20 })
{
nTask = i;
Console.WriteLine("========== nTask = {0} ===========", i);
// First use a standard lock for comparison purposes.
UseLock();
_queue.Clear();
UseSpinLock();
}
Console.WriteLine("Press a key");
Console.ReadKey();
}
private static void UpdateWithSpinLock(Data d, int i)
{
bool lockTaken = false;
try
{
_spinlock.Enter(ref lockTaken);
_queue.Enqueue(d);
_queue.Dequeue();
Thread.SpinWait(sleep);
}
finally
{
if (lockTaken) _spinlock.Exit(false);
}
}
private static void WithSpinLock()
{
for (int i = 0; i < N; i++)
{
UpdateWithSpinLock(new Data() { Name = i.ToString(), Number = i }, i);
}
}
private static void WithLock()
{
for (int i = 0; i < N; i++)
{
UpdateWithLock(new Data() { Name = i.ToString(), Number = i }, i);
}
}
private static void UseSpinLock()
{
Action[] useSpinLock = Enumerable.Range(0, nTask).Select(i => new Action(WithSpinLock)).ToArray();
Stopwatch sw = Stopwatch.StartNew();
Parallel.Invoke(useSpinLock);
sw.Stop();
Console.WriteLine("elapsed ms with spinlock: {0}", sw.ElapsedMilliseconds);
Console.WriteLine("spinlock ave: {0}", sw.ElapsedMilliseconds / (double)N);
}
static void UpdateWithLock(Data d, int i)
{
lock (_lock)
{
_queue.Enqueue(d);
_queue.Dequeue();
Thread.SpinWait(sleep);
}
}
private static void UseLock()
{
Action[] useLock = Enumerable.Range(0, nTask).Select(i => new Action(WithLock)).ToArray();
Stopwatch sw = Stopwatch.StartNew();
Parallel.Invoke(useLock);
sw.Stop();
Console.WriteLine("elapsed ms with lock: {0}", sw.ElapsedMilliseconds);
Console.WriteLine("lock ave: {0}", sw.ElapsedMilliseconds / (double)N);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment