diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/PriorityQueue.cs | 147 |
1 files changed, 95 insertions, 52 deletions
diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs index 22ffcdc..20d2049 100644 --- a/OpenSim/Framework/PriorityQueue.cs +++ b/OpenSim/Framework/PriorityQueue.cs | |||
@@ -52,6 +52,9 @@ namespace OpenSim.Framework | |||
52 | /// Number of queuest (priorities) that are processed immediately | 52 | /// Number of queuest (priorities) that are processed immediately |
53 | /// </summary. | 53 | /// </summary. |
54 | public const uint NumberOfImmediateQueues = 2; | 54 | public const uint NumberOfImmediateQueues = 2; |
55 | // first queues are immediate, so no counts | ||
56 | private static readonly uint[] m_queueCounts = {0, 0, 8, 8, 5, 4, 3, 2, 1, 1, 1, 1}; | ||
57 | // this is ava, ava, attach, <10m, 20,40,80,160m,320,640,1280, + | ||
55 | 58 | ||
56 | private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[NumberOfQueues]; | 59 | private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[NumberOfQueues]; |
57 | private Dictionary<uint, LookupItem> m_lookupTable; | 60 | private Dictionary<uint, LookupItem> m_lookupTable; |
@@ -61,10 +64,8 @@ namespace OpenSim.Framework | |||
61 | // each pass. weighted towards the higher priority queues | 64 | // each pass. weighted towards the higher priority queues |
62 | private uint m_nextQueue = 0; | 65 | private uint m_nextQueue = 0; |
63 | private uint m_countFromQueue = 0; | 66 | private uint m_countFromQueue = 0; |
64 | // first queues are imediate, so no counts | 67 | private int m_capacity; |
65 | // private uint[] m_queueCounts = { 0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1 }; | 68 | private int m_added; |
66 | private uint[] m_queueCounts = {0, 0, 8, 8, 5, 4, 3, 2, 1, 1, 1, 1}; | ||
67 | // this is ava, ava, attach, <10m, 20,40,80,160m,320,640,1280, + | ||
68 | 69 | ||
69 | // next request is a counter of the number of updates queued, it provides | 70 | // next request is a counter of the number of updates queued, it provides |
70 | // a total ordering on the updates coming through the queue and is more | 71 | // a total ordering on the updates coming through the queue and is more |
@@ -84,17 +85,29 @@ namespace OpenSim.Framework | |||
84 | 85 | ||
85 | public PriorityQueue(int capacity) | 86 | public PriorityQueue(int capacity) |
86 | { | 87 | { |
87 | m_lookupTable = new Dictionary<uint, LookupItem>(capacity); | 88 | m_capacity = capacity; |
89 | capacity /= 4; | ||
88 | 90 | ||
89 | for (int i = 0; i < m_heaps.Length; ++i) | 91 | for (int i = 0; i < m_heaps.Length; ++i) |
90 | m_heaps[i] = new MinHeap<MinHeapItem>(capacity); | 92 | m_heaps[i] = new MinHeap<MinHeapItem>(capacity); |
91 | 93 | ||
94 | m_lookupTable = new Dictionary<uint, LookupItem>(m_capacity); | ||
92 | m_nextQueue = NumberOfImmediateQueues; | 95 | m_nextQueue = NumberOfImmediateQueues; |
93 | m_countFromQueue = m_queueCounts[m_nextQueue]; | 96 | m_countFromQueue = m_queueCounts[m_nextQueue]; |
97 | m_added = 0; | ||
94 | } | 98 | } |
95 | #endregion Constructor | 99 | #endregion Constructor |
96 | 100 | ||
97 | #region PublicMethods | 101 | #region PublicMethods |
102 | public void Close() | ||
103 | { | ||
104 | for (int i = 0; i < m_heaps.Length; ++i) | ||
105 | m_heaps[i] = null; | ||
106 | m_heaps = null; | ||
107 | m_lookupTable.Clear(); | ||
108 | m_lookupTable = null; | ||
109 | } | ||
110 | |||
98 | /// <summary> | 111 | /// <summary> |
99 | /// Return the number of items in the queues | 112 | /// Return the number of items in the queues |
100 | /// </summary> | 113 | /// </summary> |
@@ -116,14 +129,21 @@ namespace OpenSim.Framework | |||
116 | public bool Enqueue(uint pqueue, EntityUpdate value) | 129 | public bool Enqueue(uint pqueue, EntityUpdate value) |
117 | { | 130 | { |
118 | LookupItem lookup; | 131 | LookupItem lookup; |
132 | IHandle lookupH; | ||
133 | UInt64 entry; | ||
119 | 134 | ||
120 | uint localid = value.Entity.LocalId; | 135 | uint localid = value.Entity.LocalId; |
121 | UInt64 entry = m_nextRequest++; | ||
122 | if (m_lookupTable.TryGetValue(localid, out lookup)) | 136 | if (m_lookupTable.TryGetValue(localid, out lookup)) |
123 | { | 137 | { |
124 | entry = lookup.Heap[lookup.Handle].EntryOrder; | 138 | lookupH = lookup.Handle; |
125 | value.Update(lookup.Heap[lookup.Handle].Value); | 139 | entry = lookup.Heap[lookupH].EntryOrder; |
126 | lookup.Heap.Remove(lookup.Handle); | 140 | value.Update(lookup.Heap[lookupH].Value); |
141 | lookup.Heap.Remove(lookupH); | ||
142 | } | ||
143 | else | ||
144 | { | ||
145 | entry = m_nextRequest++; | ||
146 | ++m_added; | ||
127 | } | 147 | } |
128 | 148 | ||
129 | pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1); | 149 | pqueue = Util.Clamp<uint>(pqueue, 0, NumberOfQueues - 1); |
@@ -134,7 +154,6 @@ namespace OpenSim.Framework | |||
134 | return true; | 154 | return true; |
135 | } | 155 | } |
136 | 156 | ||
137 | |||
138 | public void Remove(List<uint> ids) | 157 | public void Remove(List<uint> ids) |
139 | { | 158 | { |
140 | LookupItem lookup; | 159 | LookupItem lookup; |
@@ -147,6 +166,11 @@ namespace OpenSim.Framework | |||
147 | m_lookupTable.Remove(localid); | 166 | m_lookupTable.Remove(localid); |
148 | } | 167 | } |
149 | } | 168 | } |
169 | if(m_lookupTable.Count == 0 && m_added > 8 * m_capacity) | ||
170 | { | ||
171 | m_lookupTable = new Dictionary<uint, LookupItem>(m_capacity); | ||
172 | m_added = 0; | ||
173 | } | ||
150 | } | 174 | } |
151 | 175 | ||
152 | /// <summary> | 176 | /// <summary> |
@@ -156,8 +180,9 @@ namespace OpenSim.Framework | |||
156 | /// </summary> | 180 | /// </summary> |
157 | public bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue) | 181 | public bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue) |
158 | { | 182 | { |
159 | // If there is anything in imediate queues, return it first no | 183 | // If there is anything in immediate queues, return it first no |
160 | // matter what else. Breaks fairness. But very useful. | 184 | // matter what else. Breaks fairness. But very useful. |
185 | |||
161 | for (int iq = 0; iq < NumberOfImmediateQueues; iq++) | 186 | for (int iq = 0; iq < NumberOfImmediateQueues; iq++) |
162 | { | 187 | { |
163 | if (m_heaps[iq].Count > 0) | 188 | if (m_heaps[iq].Count > 0) |
@@ -177,12 +202,13 @@ namespace OpenSim.Framework | |||
177 | // to give lower numbered queues a higher priority and higher percentage | 202 | // to give lower numbered queues a higher priority and higher percentage |
178 | // of the bandwidth. | 203 | // of the bandwidth. |
179 | 204 | ||
205 | MinHeap<MinHeapItem> curheap = m_heaps[m_nextQueue]; | ||
180 | // Check for more items to be pulled from the current queue | 206 | // Check for more items to be pulled from the current queue |
181 | if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0) | 207 | if (m_countFromQueue > 0 && curheap.Count > 0) |
182 | { | 208 | { |
183 | m_countFromQueue--; | 209 | --m_countFromQueue; |
184 | 210 | ||
185 | MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); | 211 | MinHeapItem item = curheap.RemoveMin(); |
186 | m_lookupTable.Remove(item.Value.Entity.LocalId); | 212 | m_lookupTable.Remove(item.Value.Entity.LocalId); |
187 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | 213 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); |
188 | value = item.Value; | 214 | value = item.Value; |
@@ -196,35 +222,40 @@ namespace OpenSim.Framework | |||
196 | m_nextQueue++; | 222 | m_nextQueue++; |
197 | if(m_nextQueue >= NumberOfQueues) | 223 | if(m_nextQueue >= NumberOfQueues) |
198 | m_nextQueue = NumberOfImmediateQueues; | 224 | m_nextQueue = NumberOfImmediateQueues; |
225 | |||
226 | curheap = m_heaps[m_nextQueue]; | ||
227 | if (curheap.Count == 0) | ||
228 | continue; | ||
199 | 229 | ||
200 | m_countFromQueue = m_queueCounts[m_nextQueue]; | 230 | m_countFromQueue = m_queueCounts[m_nextQueue]; |
231 | --m_countFromQueue; | ||
201 | 232 | ||
202 | if (m_heaps[m_nextQueue].Count > 0) | 233 | MinHeapItem item = curheap.RemoveMin(); |
203 | { | 234 | m_lookupTable.Remove(item.Value.Entity.LocalId); |
204 | m_countFromQueue--; | 235 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); |
205 | 236 | value = item.Value; | |
206 | MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); | 237 | return true; |
207 | m_lookupTable.Remove(item.Value.Entity.LocalId); | ||
208 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | ||
209 | value = item.Value; | ||
210 | return true; | ||
211 | } | ||
212 | } | 238 | } |
213 | 239 | ||
214 | timeinqueue = 0; | 240 | timeinqueue = 0; |
215 | value = default(EntityUpdate); | 241 | value = default(EntityUpdate); |
242 | if(m_lookupTable.Count == 0 && m_added > 8 * m_capacity) | ||
243 | { | ||
244 | m_lookupTable = new Dictionary<uint, LookupItem>(m_capacity); | ||
245 | m_added = 0; | ||
246 | } | ||
216 | return false; | 247 | return false; |
217 | } | 248 | } |
218 | 249 | ||
219 | public bool TryOrderedDequeue(out EntityUpdate value, out Int32 timeinqueue) | 250 | public bool TryOrderedDequeue(out EntityUpdate value, out Int32 timeinqueue) |
220 | { | 251 | { |
221 | // If there is anything in imediate queues, return it first no | 252 | MinHeap<MinHeapItem> curheap; |
222 | // matter what else. Breaks fairness. But very useful. | 253 | for (int iq = 0; iq < NumberOfQueues; ++iq) |
223 | for (int iq = 0; iq < NumberOfQueues; iq++) | ||
224 | { | 254 | { |
225 | if (m_heaps[iq].Count > 0) | 255 | curheap = m_heaps[iq]; |
256 | if (curheap.Count > 0) | ||
226 | { | 257 | { |
227 | MinHeapItem item = m_heaps[iq].RemoveMin(); | 258 | MinHeapItem item = curheap.RemoveMin(); |
228 | m_lookupTable.Remove(item.Value.Entity.LocalId); | 259 | m_lookupTable.Remove(item.Value.Entity.LocalId); |
229 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); | 260 | timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); |
230 | value = item.Value; | 261 | value = item.Value; |
@@ -234,6 +265,11 @@ namespace OpenSim.Framework | |||
234 | 265 | ||
235 | timeinqueue = 0; | 266 | timeinqueue = 0; |
236 | value = default(EntityUpdate); | 267 | value = default(EntityUpdate); |
268 | if(m_lookupTable.Count == 0 && m_added > 8 * m_capacity) | ||
269 | { | ||
270 | m_lookupTable = new Dictionary<uint, LookupItem>(m_capacity); | ||
271 | m_added = 0; | ||
272 | } | ||
237 | return false; | 273 | return false; |
238 | } | 274 | } |
239 | 275 | ||
@@ -244,7 +280,7 @@ namespace OpenSim.Framework | |||
244 | public void Reprioritize(UpdatePriorityHandler handler) | 280 | public void Reprioritize(UpdatePriorityHandler handler) |
245 | { | 281 | { |
246 | MinHeapItem item; | 282 | MinHeapItem item; |
247 | foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values)) | 283 | foreach (LookupItem lookup in new List<LookupItem>(m_lookupTable.Values)) |
248 | { | 284 | { |
249 | if (lookup.Heap.TryGetValue(lookup.Handle, out item)) | 285 | if (lookup.Heap.TryGetValue(lookup.Handle, out item)) |
250 | { | 286 | { |
@@ -270,7 +306,7 @@ namespace OpenSim.Framework | |||
270 | { | 306 | { |
271 | // m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID); | 307 | // m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID); |
272 | lookup.Heap.Remove(lookup.Handle); | 308 | lookup.Heap.Remove(lookup.Handle); |
273 | this.m_lookupTable.Remove(localid); | 309 | m_lookupTable.Remove(localid); |
274 | } | 310 | } |
275 | } | 311 | } |
276 | } | 312 | } |
@@ -292,48 +328,55 @@ namespace OpenSim.Framework | |||
292 | private struct MinHeapItem : IComparable<MinHeapItem> | 328 | private struct MinHeapItem : IComparable<MinHeapItem> |
293 | { | 329 | { |
294 | private EntityUpdate value; | 330 | private EntityUpdate value; |
295 | internal EntityUpdate Value { | 331 | internal EntityUpdate Value |
296 | get { | 332 | { |
297 | return this.value; | 333 | get |
334 | { | ||
335 | return value; | ||
298 | } | 336 | } |
299 | } | 337 | } |
300 | 338 | ||
301 | private uint pqueue; | 339 | private uint pqueue; |
302 | internal uint PriorityQueue { | 340 | internal uint PriorityQueue |
303 | get { | 341 | { |
304 | return this.pqueue; | 342 | get |
343 | { | ||
344 | return pqueue; | ||
305 | } | 345 | } |
306 | } | 346 | } |
307 | 347 | ||
308 | private Int32 entrytime; | 348 | private Int32 entrytime; |
309 | internal Int32 EntryTime { | 349 | internal Int32 EntryTime |
310 | get { | 350 | { |
311 | return this.entrytime; | 351 | get |
352 | { | ||
353 | return entrytime; | ||
312 | } | 354 | } |
313 | } | 355 | } |
314 | 356 | ||
315 | private UInt64 entryorder; | 357 | private UInt64 entryorder; |
316 | internal UInt64 EntryOrder | 358 | internal UInt64 EntryOrder |
317 | { | 359 | { |
318 | get { | 360 | get |
319 | return this.entryorder; | 361 | { |
362 | return entryorder; | ||
320 | } | 363 | } |
321 | } | 364 | } |
322 | 365 | ||
323 | internal MinHeapItem(uint pqueue, MinHeapItem other) | 366 | internal MinHeapItem(uint _pqueue, MinHeapItem other) |
324 | { | 367 | { |
325 | this.entrytime = other.entrytime; | 368 | entrytime = other.entrytime; |
326 | this.entryorder = other.entryorder; | 369 | entryorder = other.entryorder; |
327 | this.value = other.value; | 370 | value = other.value; |
328 | this.pqueue = pqueue; | 371 | pqueue = _pqueue; |
329 | } | 372 | } |
330 | 373 | ||
331 | internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value) | 374 | internal MinHeapItem(uint _pqueue, UInt64 _entryorder, EntityUpdate _value) |
332 | { | 375 | { |
333 | this.entrytime = Util.EnvironmentTickCount(); | 376 | entrytime = Util.EnvironmentTickCount(); |
334 | this.entryorder = entryorder; | 377 | entryorder = _entryorder; |
335 | this.value = value; | 378 | value = _value; |
336 | this.pqueue = pqueue; | 379 | pqueue = _pqueue; |
337 | } | 380 | } |
338 | 381 | ||
339 | public override string ToString() | 382 | public override string ToString() |