-
-
Save kenegozi/24b9012a49392c4e458b to your computer and use it in GitHub Desktop.
This file contains 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
class Generator | |
{ | |
int val; | |
object locker = new object(); | |
public int GetNonLocked() | |
{ | |
return val++; | |
} | |
public int GetLocked() | |
{ | |
lock (locker) | |
return val++; | |
} | |
public int GetInterlocked() | |
{ | |
// Interlocked.Increment is doing ++value and not value++, so we decrement 1 | |
// of the resulted operation | |
return Interlocked.Increment(ref val) - 1; | |
} | |
} | |
internal class Program | |
{ | |
public static void Main() | |
{ | |
var gen = new Generator(); | |
var many = 100000; | |
var repeats = 10; | |
double nonLocked = 0, locked = 0, interlocked = 0; | |
gen = new Generator(); | |
repeats.TimesDo(() => nonLocked += MeasureTime(() => many.TimesDo(() => gen.GetNonLocked()))); | |
gen = new Generator(); | |
repeats.TimesDo(() => locked += MeasureTime(() => many.TimesDo(() => gen.GetLocked()))); | |
gen = new Generator(); | |
repeats.TimesDo(() => interlocked += MeasureTime(() => many.TimesDo(() => gen.GetInterlocked()))); | |
Console.WriteLine("avg time for no-lock is {0} milliseconds", nonLocked / repeats); | |
Console.WriteLine("avg time for lock is {0} milliseconds", locked / repeats); | |
Console.WriteLine("avg time for interlock is {0} milliseconds", interlocked / repeats); | |
nonLocked = 0; locked = 0; interlocked = 0; | |
gen = new Generator(); | |
repeats.TimesDo(() => nonLocked += MeasureTime(() => many.TimesDoAsync(() => gen.GetNonLocked()))); | |
gen = new Generator(); | |
repeats.TimesDo(() => locked += MeasureTime(() => many.TimesDoAsync(() => gen.GetLocked()))); | |
gen = new Generator(); | |
repeats.TimesDo(() => interlocked += MeasureTime(() => many.TimesDoAsync(() => gen.GetInterlocked()))); | |
Console.WriteLine("avg time for async no-lock is {0} milliseconds", nonLocked / repeats); | |
Console.WriteLine("avg time for async lock is {0} milliseconds", locked / repeats); | |
Console.WriteLine("avg time for async interlock is {0} milliseconds", interlocked / repeats); | |
} | |
static void MeasureTime(Action action) | |
{ | |
var watch = Stopwatch.StartNew(); | |
action(); | |
watch.Stop(); | |
Console.WriteLine(watch.ElapsedMilliseconds + "milliseconds"); | |
} | |
} | |
static class IntTimesDoExtension | |
{ | |
public static void TimesDo(this int times, Action action) | |
{ | |
for (var i = 0; i < times; ++i) | |
action(); | |
} | |
public static void TimesDoAsync(this int times, Action action) | |
{ | |
SpawnAndWait(times, action); | |
} | |
static void SpawnAndWait(int count, Action action) | |
{ | |
var reset = new ManualResetEvent(false); | |
var completed = count; | |
for (var i = 0; i < count; ++i) | |
{ | |
ThreadPool.QueueUserWorkItem(d => | |
{ | |
action(); | |
if (Interlocked.Decrement(ref completed) == 0) | |
reset.Set(); | |
}); | |
} | |
WaitHandle.WaitAll(new[] { reset }); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment