Created
March 17, 2015 07:02
-
-
Save rogeralsing/98f9c701a092fcd2925b to your computer and use it in GitHub Desktop.
Naive threadpool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Threading; | |
namespace NaiveThreadPool | |
{ | |
class Program | |
{ | |
static void Main() | |
{ | |
int count = 0; | |
var myThreadpool = new MyThreadPool(10); | |
const int totalWork = 10000000; | |
var workDone = new ManualResetEventSlim(false); | |
Console.WriteLine("Press any key to start.."); | |
Console.ReadKey(); | |
var sw = Stopwatch.StartNew(); | |
for (int i = 0; i < totalWork; i++) | |
{ | |
myThreadpool.AddWork(() => | |
{ | |
if (Interlocked.Increment(ref count) == totalWork) | |
{ | |
workDone.Set(); | |
} | |
}); | |
} | |
workDone.Wait(); | |
Console.WriteLine(sw.Elapsed); | |
Console.ReadLine(); | |
} | |
} | |
public class MyThreadPool | |
{ | |
private volatile int _index; | |
private readonly List<Worker> _workers = new List<Worker>(); | |
public MyThreadPool(int nrOfWorkers) | |
{ | |
for (int i = 0; i < nrOfWorkers; i++) | |
{ | |
var worker = new Worker(); | |
_workers.Add(worker); | |
} | |
} | |
public void AddWork(Action work) | |
{ | |
//using volatile instead of interlocked, no need to be exact, gaining 20% perf | |
_workers[_index ++ % _workers.Count].AddWork(work); | |
} | |
} | |
public class Worker | |
{ | |
private readonly ConcurrentQueue<Action> _work = new ConcurrentQueue<Action>(); | |
private readonly ManualResetEventSlim _event = new ManualResetEventSlim(false); | |
public Worker() | |
{ | |
var thread = new Thread(() => | |
{ | |
while (true) | |
{ | |
//suspend if no more work is present | |
_event.Wait(); | |
Action action; | |
while (_work.TryDequeue(out action)) | |
{ | |
action(); | |
} | |
if (_work.Count == 0) | |
{ | |
_event.Reset(); | |
} | |
if (_work.Count > 0) | |
{ | |
_event.Set(); | |
} | |
} | |
}) | |
{ | |
IsBackground = true | |
}; | |
thread.Start(); | |
} | |
public void AddWork(Action work) | |
{ | |
_work.Enqueue(work); | |
_event.Set(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This one does about 8 000 000 actions per second on my machine.