Skip to content

Commit a468110

Browse files
author
David R. MacIver
committed
flush before reserve, as reserve algorithm only looks at contents of intervals
1 parent 19483b6 commit a468110

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

projects/client/RabbitMQ.Client/src/util/IntAllocator.cs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,17 @@ public static IntervalList Merge(IntervalList x, IntervalList y)
118118
return x;
119119
}
120120

121-
public static IntervalList FromArray(int[] xs)
121+
public static IntervalList FromArray(int[] xs, int length)
122122
{
123123
Array.Sort(xs);
124124

125125
IntervalList result = null;
126126
IntervalList current = null;
127127

128128
int i = 0;
129-
while(i < xs.Length){
129+
while(i < length){
130130
int start = i;
131-
while((i < xs.Length - 1) && (xs[i + 1] == xs[i] + 1))
131+
while((i < length - 1) && (xs[i + 1] == xs[i] + 1))
132132
i++;
133133

134134
IntervalList interval = new IntervalList(start, i);
@@ -178,6 +178,16 @@ public int Allocate()
178178
}
179179
}
180180

181+
private void Flush()
182+
{
183+
if(unsortedCount > 0)
184+
{
185+
Base = IntervalList.Merge(Base, IntervalList.FromArray(unsorted, unsortedCount));
186+
unsortedCount = 0;
187+
}
188+
}
189+
190+
181191
/**
182192
* Make the provided integer available for allocation again. This operation
183193
* runs in amortized O(sqrt(range size)) time: About every sqrt(range size)
@@ -189,15 +199,23 @@ public int Allocate()
189199
*/
190200
public void Free(int id)
191201
{
192-
if(unsortedCount >= unsorted.Length){
193-
Base = IntervalList.Merge(Base, IntervalList.FromArray(unsorted));
194-
unsortedCount = 0;
202+
if(unsortedCount >= unsorted.Length)
203+
{
204+
Flush();
195205
}
196206
unsorted[unsortedCount++] = id;
197207
}
198208

199209
public bool Reserve(int id)
200210
{
211+
// We always flush before reserving because the only way to determine
212+
// if an ID is in the unsorted array is through a linear scan. This leads
213+
// us to the potentially expensive situation where there is a large unsorted
214+
// array and we reserve several IDs, incurring the cost of the scan each time.
215+
// Flushing makes sure the array is always empty and does no additional work if
216+
// reserve is called twice.
217+
Flush();
218+
201219
IntervalList current = Base;
202220

203221
while(current != null)

0 commit comments

Comments
 (0)