Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 079f50c

Browse files
author
Greg Eakin
committed
Move the heap processing out of the lock.
1 parent 980e452 commit 079f50c

File tree

8 files changed

+74
-43
lines changed

8 files changed

+74
-43
lines changed

FunProgLib/heap/LazyBinomialHeap.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public Tree(int rank, T x, List<Tree>.Node list)
3535

3636
public static Lazy<List<Tree>.Node> Empty { get; } = new Lazy<List<Tree>.Node>(() => List<Tree>.Empty);
3737

38-
public static bool IsEmpty(Lazy<List<Tree>.Node> heap) => List<Tree>.IsEmpty(heap.Value);
38+
public static bool IsEmpty(Lazy<List<Tree>.Node> heap) =>
39+
heap == null || ReferenceEquals(Empty, heap) || List<Tree>.IsEmpty(heap.Value);
3940

4041
public static int Rank(Tree t) => t.Rank;
4142

FunProgLib/heap/SplayHeap.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,4 @@ public static Heap DeleteMin(Heap t)
109109
return new Heap(DeleteMin(t.A.A), t.A.X, new Heap(t.A.B, t.X, t.B));
110110
}
111111
}
112-
}
112+
}

FunProgTests/ephemeral/DictionaryInterlockTests.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ private void InsertAction()
2929
var word = NextWord(10);
3030
while (true)
3131
{
32-
var workingSet = _set;
32+
var localCopy = _set;
3333
Thread.MemoryBarrier();
3434
// 99 ms, 13,072 calls
35-
var newSet = SplayHeap<string>.Insert(word, workingSet);
35+
var newSet = SplayHeap<string>.Insert(word, localCopy);
3636
// 3 ms, 13,072 calls
37-
var oldSet = Interlocked.CompareExchange(ref _set, newSet, workingSet);
38-
if (ReferenceEquals(oldSet, workingSet))
37+
var oldSet = Interlocked.CompareExchange(ref _set, newSet, localCopy);
38+
if (ReferenceEquals(oldSet, localCopy))
3939
{
4040
// 3,000 calls
4141
break;
@@ -49,31 +49,32 @@ private void RemoveAction()
4949
{
5050
for (var i = 0; i < Count; i++)
5151
{
52+
SplayHeap<string>.Heap localCopy;
5253
while (true)
5354
{
54-
var workingSet = _set;
55+
localCopy = _set;
5556
Thread.MemoryBarrier();
5657
// 13 ms, 66,042 calls
57-
if (SplayHeap<string>.IsEmpty(workingSet))
58+
if (SplayHeap<string>.IsEmpty(localCopy))
5859
{
60+
Thread.Yield();
5961
continue;
6062
}
6163

6264
// 15 ms, 7,594 calls
63-
var unused = SplayHeap<string>.FindMin(workingSet);
64-
// 15 ms, 7,594 calls
65-
var newSet = SplayHeap<string>.DeleteMin(workingSet);
65+
var newSet = SplayHeap<string>.DeleteMin(localCopy);
6666
// 2 ms, 7,594 calls
67-
var oldSet = Interlocked.CompareExchange(ref _set, newSet, workingSet);
68-
if (ReferenceEquals(oldSet, workingSet))
69-
{
70-
// 3,000 calls
67+
var oldSet = Interlocked.CompareExchange(ref _set, newSet, localCopy);
68+
if (ReferenceEquals(oldSet, localCopy))
7169
break;
72-
}
7370
}
71+
72+
// 3,000 calls
73+
var unused = SplayHeap<string>.FindMin(localCopy);
7474
}
7575
}
7676

77+
//[AssertTraffic(AllocatedObjectsCount = 15128)]
7778
[TestMethod]
7879
public void Test1()
7980
{
@@ -85,6 +86,8 @@ public void Test1()
8586
}
8687

8788
Task.WaitAll(taskList.ToArray());
89+
90+
Assert.IsNull(_set);
8891
}
8992
}
90-
}
93+
}

FunProgTests/ephemeral/DictionaryLockTests.cs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,26 +53,40 @@ public bool Insert(string word)
5353

5454
public bool Remove(out string item)
5555
{
56-
item = default(string);
57-
5856
// 58 ms, 3,000 calls
57+
SplayHeap<string>.Heap localCopy;
5958
lock (_lockObject)
6059
{
6160
while (!_token.IsCancellationRequested && SplayHeap<string>.IsEmpty(_set))
6261
// 33 ms, 1,609 calls
6362
Monitor.Wait(_lockObject);
6463

6564
if (SplayHeap<string>.IsEmpty(_set))
65+
{
66+
item = default(string);
6667
return false;
68+
}
6769

6870
// 2 ms, 3,000 calls
69-
item = SplayHeap<string>.FindMin(_set);
70-
// 2 ms, 3,000 calls
71-
_set = SplayHeap<string>.DeleteMin(_set);
71+
localCopy = _set;
72+
_set = SplayHeap<string>.DeleteMin(localCopy);
7273
}
7374

75+
// 2 ms, 3,000 calls
76+
item = SplayHeap<string>.FindMin(localCopy);
7477
return true;
7578
}
79+
80+
public bool IsEmpty
81+
{
82+
get
83+
{
84+
lock (_lockObject)
85+
{
86+
return SplayHeap<string>.IsEmpty(_set);
87+
}
88+
}
89+
}
7690
}
7791

7892
[TestClass]
@@ -81,7 +95,7 @@ public class DictionaryLockTests : DictionaryTests
8195
// 157 ms, 10 calls
8296
private void InsertAction(object ojb)
8397
{
84-
var map = (DictionaryLock<string>)ojb;
98+
var map = (DictionaryLock<string>) ojb;
8599
for (var i = 0; i < Count; i++)
86100
{
87101
// 5 ms, 3,000 calls
@@ -96,12 +110,12 @@ private void InsertAction(object ojb)
96110
// 98 ms, 10 calls
97111
private static void RemoveAction(object ojb)
98112
{
99-
var map = (DictionaryLock<string>)ojb;
113+
var map = (DictionaryLock<string>) ojb;
100114
for (var i = 0; i < Count; i++)
101115
{
102116
var removed = map.Remove(out var item);
103117
if (!removed)
104-
return;
118+
break;
105119

106120
var unused = Convert.FromBase64String(item);
107121
// Console.WriteLine(string.Join(", ", unused));
@@ -124,6 +138,7 @@ public void Test1()
124138
}
125139

126140
Task.WaitAll(taskList.ToArray());
141+
Assert.IsTrue(dictionary.IsEmpty);
127142
}
128143
}
129144
}

FunProgTests/ephemeral/DictionaryRwLockTests.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,16 @@ private void RemoveAction()
4343
{
4444
for (var i = 0; i < Count; i++)
4545
{
46+
SplayHeap<string>.Heap localCopy;
4647
while (true)
4748
{
4849
_lockObject.EnterWriteLock();
4950
try
5051
{
5152
if (!SplayHeap<string>.IsEmpty(_set))
5253
{
53-
var unused = SplayHeap<string>.FindMin(_set);
54-
_set = SplayHeap<string>.DeleteMin(_set);
54+
localCopy = _set;
55+
_set = SplayHeap<string>.DeleteMin(localCopy);
5556
break;
5657
}
5758
}
@@ -62,6 +63,8 @@ private void RemoveAction()
6263

6364
Thread.Yield();
6465
}
66+
67+
var unused = SplayHeap<string>.FindMin(localCopy);
6568
}
6669
}
6770

@@ -76,6 +79,7 @@ public void Test1()
7679
}
7780

7881
Task.WaitAll(taskList.ToArray());
82+
Assert.IsNull(_set);
7983
}
8084

8185
public void Dispose()

FunProgTests/ephemeral/DictionarySemaphoreTests.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,9 @@ private void InsertAction()
3434
_semaphore.Wait();
3535
try
3636
{
37-
var localSet = _set;
3837
Interlocked.MemoryBarrier();
3938
// 43 ms, 3,000 calls
40-
var newSet = SplayHeap<string>.Insert(word, localSet);
39+
var newSet = SplayHeap<string>.Insert(word, _set);
4140
Interlocked.Exchange(ref _set, newSet);
4241
}
4342
finally
@@ -52,21 +51,23 @@ private void RemoveAction()
5251
{
5352
for (var i = 0; i < Count; i++)
5453
{
54+
SplayHeap<string>.Heap localCopy;
5555
while (true)
5656
{
5757
// 294 ms, 3,000 calls
5858
_semaphore.Wait();
5959
try
6060
{
61-
var localSet = _set;
61+
localCopy = _set;
6262
Interlocked.MemoryBarrier();
63-
if (SplayHeap<string>.IsEmpty(localSet))
63+
if (SplayHeap<string>.IsEmpty(localCopy))
64+
{
65+
Thread.Yield();
6466
continue;
67+
}
6568

66-
// 3 ms, 3,000 calls
67-
var unused = SplayHeap<string>.FindMin(localSet);
6869
// 4 ms, 3,000 calls
69-
var newSet = SplayHeap<string>.DeleteMin(localSet);
70+
var newSet = SplayHeap<string>.DeleteMin(localCopy);
7071
Interlocked.Exchange(ref _set, newSet);
7172
break;
7273
}
@@ -75,6 +76,9 @@ private void RemoveAction()
7576
_semaphore.Release();
7677
}
7778
}
79+
80+
// 3 ms, 3,000 calls
81+
var unused = SplayHeap<string>.FindMin(localCopy);
7882
}
7983
}
8084

@@ -89,11 +93,12 @@ public void Test1()
8993
}
9094

9195
Task.WaitAll(taskList.ToArray());
96+
Assert.IsNull(_set);
9297
}
9398

9499
public void Dispose()
95100
{
96101
_semaphore.Dispose();
97102
}
98103
}
99-
}
104+
}

FunProgTests/ephemeral/DictionarySingleThreadTests.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ private int RemoveAction(int count)
3838
if (SplayHeap<string>.IsEmpty(_set))
3939
return i;
4040

41-
var unused = SplayHeap<string>.FindMin(_set);
42-
_set = SplayHeap<string>.DeleteMin(_set);
41+
var localCopy = _set;
42+
_set = SplayHeap<string>.DeleteMin(localCopy);
43+
var unused = SplayHeap<string>.FindMin(localCopy);
4344
i++;
4445
}
4546

@@ -49,10 +50,10 @@ private int RemoveAction(int count)
4950
[TestMethod]
5051
public void Test1()
5152
{
52-
var size = Threads * Count / 2;
53+
const int size = Threads * Count / 2;
5354
var writes = 0;
5455
var reads = 0;
55-
while (writes < size && reads < size)
56+
while (writes < size || reads < size)
5657
{
5758
var count = _random.Next(50);
5859
var next = _random.Next(10);
@@ -69,6 +70,8 @@ public void Test1()
6970
reads += RemoveAction(count);
7071
}
7172
}
73+
74+
Assert.IsNull(_set);
7275
}
7376
}
7477
}

FunProgTests/ephemeral/MultiInterlockMapTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ private void WriteAction()
2828
var word = NextWord(1);
2929
while (true)
3030
{
31-
var workingSet = _set;
31+
var localCopy = _set;
3232
Thread.MemoryBarrier();
33-
var newSet = RedBlackSet<string>.Insert(word, workingSet);
34-
var oldSet = Interlocked.CompareExchange(ref _set, newSet, workingSet);
35-
if (ReferenceEquals(oldSet, workingSet))
33+
var newSet = RedBlackSet<string>.Insert(word, localCopy);
34+
var oldSet = Interlocked.CompareExchange(ref _set, newSet, localCopy);
35+
if (ReferenceEquals(oldSet, localCopy))
3636
break;
3737
}
3838
}

0 commit comments

Comments
 (0)