diff options
author | Sean Dague | 2007-12-07 21:30:01 +0000 |
---|---|---|
committer | Sean Dague | 2007-12-07 21:30:01 +0000 |
commit | 0aa982c25271f91e1b3002022d3e02e55707d476 (patch) | |
tree | 8ca6318c6ef76140887a08d4c99186d2f72b2c26 /OpenSim/Region/ClientStack/PacketQueue.cs | |
parent | further screwing around with the PacketQueue data structure. (diff) | |
download | opensim-SC-0aa982c25271f91e1b3002022d3e02e55707d476.zip opensim-SC-0aa982c25271f91e1b3002022d3e02e55707d476.tar.gz opensim-SC-0aa982c25271f91e1b3002022d3e02e55707d476.tar.bz2 opensim-SC-0aa982c25271f91e1b3002022d3e02e55707d476.tar.xz |
move to PacketQueue for throttling. This has been tested with a couple
of people, but is enough of a change that more should try it out. This
removes 500 lines from ClientView.cs in the process.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ClientStack/PacketQueue.cs | 142 |
1 files changed, 42 insertions, 100 deletions
diff --git a/OpenSim/Region/ClientStack/PacketQueue.cs b/OpenSim/Region/ClientStack/PacketQueue.cs index f2d270c..5deede5 100644 --- a/OpenSim/Region/ClientStack/PacketQueue.cs +++ b/OpenSim/Region/ClientStack/PacketQueue.cs | |||
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ClientStack | |||
44 | { | 44 | { |
45 | public class PacketQueue | 45 | public class PacketQueue |
46 | { | 46 | { |
47 | private Queue<QueItem> SendQueue; | 47 | private BlockingQueue<QueItem> SendQueue; |
48 | 48 | ||
49 | private Queue<QueItem> IncomingPacketQueue; | 49 | private Queue<QueItem> IncomingPacketQueue; |
50 | private Queue<QueItem> OutgoingPacketQueue; | 50 | private Queue<QueItem> OutgoingPacketQueue; |
@@ -76,8 +76,9 @@ namespace OpenSim.Region.ClientStack | |||
76 | private PacketThrottle TextureThrottle; | 76 | private PacketThrottle TextureThrottle; |
77 | private PacketThrottle TotalThrottle; | 77 | private PacketThrottle TotalThrottle; |
78 | 78 | ||
79 | private long LastThrottle; | 79 | // private long LastThrottle; |
80 | private long ThrottleInterval; | 80 | // private long ThrottleInterval; |
81 | private Timer throttleTimer; | ||
81 | 82 | ||
82 | public PacketQueue() | 83 | public PacketQueue() |
83 | { | 84 | { |
@@ -86,7 +87,7 @@ namespace OpenSim.Region.ClientStack | |||
86 | // in it to process. it's an on-purpose threadlock though because | 87 | // in it to process. it's an on-purpose threadlock though because |
87 | // without it, the clientloop will suck up all sim resources. | 88 | // without it, the clientloop will suck up all sim resources. |
88 | 89 | ||
89 | SendQueue = new Queue<QueItem>(); | 90 | SendQueue = new BlockingQueue<QueItem>(); |
90 | 91 | ||
91 | IncomingPacketQueue = new Queue<QueItem>(); | 92 | IncomingPacketQueue = new Queue<QueItem>(); |
92 | OutgoingPacketQueue = new Queue<QueItem>(); | 93 | OutgoingPacketQueue = new Queue<QueItem>(); |
@@ -110,10 +111,15 @@ namespace OpenSim.Region.ClientStack | |||
110 | // Total Throttle trumps all | 111 | // Total Throttle trumps all |
111 | // Number of bytes allowed to go out per second. (256kbps per client) | 112 | // Number of bytes allowed to go out per second. (256kbps per client) |
112 | TotalThrottle = new PacketThrottle(0, 162144, 1536000); | 113 | TotalThrottle = new PacketThrottle(0, 162144, 1536000); |
114 | |||
115 | throttleTimer = new Timer((int)(throttletimems/throttleTimeDivisor)); | ||
116 | throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed); | ||
117 | throttleTimer.Start(); | ||
113 | 118 | ||
114 | // TIMERS needed for this | 119 | // TIMERS needed for this |
115 | LastThrottle = DateTime.Now.Ticks; | 120 | // LastThrottle = DateTime.Now.Ticks; |
116 | ThrottleInterval = (long)(throttletimems/throttleTimeDivisor); | 121 | // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor); |
122 | |||
117 | } | 123 | } |
118 | 124 | ||
119 | /* STANDARD QUEUE MANIPULATION INTERFACES */ | 125 | /* STANDARD QUEUE MANIPULATION INTERFACES */ |
@@ -123,7 +129,7 @@ namespace OpenSim.Region.ClientStack | |||
123 | { | 129 | { |
124 | // We could micro lock, but that will tend to actually | 130 | // We could micro lock, but that will tend to actually |
125 | // probably be worse than just synchronizing on SendQueue | 131 | // probably be worse than just synchronizing on SendQueue |
126 | lock (SendQueue) { | 132 | lock (this) { |
127 | switch (item.throttleType) | 133 | switch (item.throttleType) |
128 | { | 134 | { |
129 | case ThrottleOutPacketType.Resend: | 135 | case ThrottleOutPacketType.Resend: |
@@ -159,12 +165,14 @@ namespace OpenSim.Region.ClientStack | |||
159 | 165 | ||
160 | public QueItem Dequeue() | 166 | public QueItem Dequeue() |
161 | { | 167 | { |
162 | if (ThrottlingTime()) { | 168 | return SendQueue.Dequeue(); |
163 | ProcessThrottle(); | 169 | } |
164 | } | 170 | |
165 | lock (SendQueue) { | 171 | public void Close() |
166 | return SendQueue.Dequeue(); | 172 | { |
167 | } | 173 | // one last push |
174 | ProcessThrottle(); | ||
175 | throttleTimer.Stop(); | ||
168 | } | 176 | } |
169 | 177 | ||
170 | private void ResetCounters() | 178 | private void ResetCounters() |
@@ -192,15 +200,15 @@ namespace OpenSim.Region.ClientStack | |||
192 | 200 | ||
193 | // Run through our wait queues and flush out allotted numbers of bytes into the process queue | 201 | // Run through our wait queues and flush out allotted numbers of bytes into the process queue |
194 | 202 | ||
195 | private bool ThrottlingTime() | 203 | // private bool ThrottlingTime() |
196 | { | 204 | // { |
197 | if(DateTime.Now.Ticks < (LastThrottle + ThrottleInterval)) { | 205 | // if(DateTime.Now.Ticks > (LastThrottle + ThrottleInterval)) { |
198 | LastThrottle = DateTime.Now.Ticks; | 206 | // LastThrottle = DateTime.Now.Ticks; |
199 | return true; | 207 | // return true; |
200 | } else { | 208 | // } else { |
201 | return false; | 209 | // return false; |
202 | } | 210 | // } |
203 | } | 211 | // } |
204 | 212 | ||
205 | public void ProcessThrottle() | 213 | public void ProcessThrottle() |
206 | { | 214 | { |
@@ -216,8 +224,9 @@ namespace OpenSim.Region.ClientStack | |||
216 | 224 | ||
217 | // We're going to dequeue all of the saved up packets until | 225 | // We're going to dequeue all of the saved up packets until |
218 | // we've hit the throttle limit or there's no more packets to send | 226 | // we've hit the throttle limit or there's no more packets to send |
219 | lock (SendQueue) { | 227 | lock (this) { |
220 | ResetCounters(); | 228 | ResetCounters(); |
229 | // MainLog.Instance.Verbose("THROTTLE", "Entering Throttle"); | ||
221 | while (TotalThrottle.UnderLimit() && PacketsWaiting() && | 230 | while (TotalThrottle.UnderLimit() && PacketsWaiting() && |
222 | (throttleLoops <= MaxThrottleLoops)) | 231 | (throttleLoops <= MaxThrottleLoops)) |
223 | { | 232 | { |
@@ -280,86 +289,16 @@ namespace OpenSim.Region.ClientStack | |||
280 | AssetThrottle.Add(qpack.Packet.ToBytes().Length); | 289 | AssetThrottle.Add(qpack.Packet.ToBytes().Length); |
281 | } | 290 | } |
282 | } | 291 | } |
292 | // MainLog.Instance.Verbose("THROTTLE", "Processed " + throttleLoops + " packets"); | ||
293 | |||
283 | } | 294 | } |
284 | } | 295 | } |
285 | 296 | ||
286 | private void throttleTimer_Elapsed(object sender, ElapsedEventArgs e) | 297 | private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) |
287 | { | 298 | { |
288 | ResetCounters(); | 299 | // just to change the signature, and that ProcessThrottle |
289 | 300 | // will be used elsewhere possibly | |
290 | // I was considering this.. Will an event fire if the thread it's on is blocked? | 301 | ProcessThrottle(); |
291 | |||
292 | // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long | ||
293 | // The General overhead of the UDP protocol gets sent to the queue un-throttled by this | ||
294 | // so This'll pick up about around the right time. | ||
295 | |||
296 | int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. | ||
297 | int throttleLoops = 0; | ||
298 | |||
299 | // We're going to dequeue all of the saved up packets until | ||
300 | // we've hit the throttle limit or there's no more packets to send | ||
301 | while (TotalThrottle.UnderLimit() && PacketsWaiting() && | ||
302 | (throttleLoops <= MaxThrottleLoops)) | ||
303 | { | ||
304 | throttleLoops++; | ||
305 | //Now comes the fun part.. we dump all our elements into PacketQueue that we've saved up. | ||
306 | if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0) | ||
307 | { | ||
308 | QueItem qpack = ResendOutgoingPacketQueue.Dequeue(); | ||
309 | |||
310 | SendQueue.Enqueue(qpack); | ||
311 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
312 | ResendThrottle.Add(qpack.Packet.ToBytes().Length); | ||
313 | } | ||
314 | if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0) | ||
315 | { | ||
316 | QueItem qpack = LandOutgoingPacketQueue.Dequeue(); | ||
317 | |||
318 | SendQueue.Enqueue(qpack); | ||
319 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
320 | LandThrottle.Add(qpack.Packet.ToBytes().Length); | ||
321 | } | ||
322 | if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0) | ||
323 | { | ||
324 | QueItem qpack = WindOutgoingPacketQueue.Dequeue(); | ||
325 | |||
326 | SendQueue.Enqueue(qpack); | ||
327 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
328 | WindThrottle.Add(qpack.Packet.ToBytes().Length); | ||
329 | } | ||
330 | if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0) | ||
331 | { | ||
332 | QueItem qpack = CloudOutgoingPacketQueue.Dequeue(); | ||
333 | |||
334 | SendQueue.Enqueue(qpack); | ||
335 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
336 | CloudThrottle.Add(qpack.Packet.ToBytes().Length); | ||
337 | } | ||
338 | if (TaskThrottle.UnderLimit() && TaskOutgoingPacketQueue.Count > 0) | ||
339 | { | ||
340 | QueItem qpack = TaskOutgoingPacketQueue.Dequeue(); | ||
341 | |||
342 | SendQueue.Enqueue(qpack); | ||
343 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
344 | TaskThrottle.Add(qpack.Packet.ToBytes().Length); | ||
345 | } | ||
346 | if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0) | ||
347 | { | ||
348 | QueItem qpack = TextureOutgoingPacketQueue.Dequeue(); | ||
349 | |||
350 | SendQueue.Enqueue(qpack); | ||
351 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
352 | TextureThrottle.Add(qpack.Packet.ToBytes().Length); | ||
353 | } | ||
354 | if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0) | ||
355 | { | ||
356 | QueItem qpack = AssetOutgoingPacketQueue.Dequeue(); | ||
357 | |||
358 | SendQueue.Enqueue(qpack); | ||
359 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
360 | AssetThrottle.Add(qpack.Packet.ToBytes().Length); | ||
361 | } | ||
362 | } | ||
363 | } | 302 | } |
364 | 303 | ||
365 | private void ThrottleCheck(ref PacketThrottle throttle, ref Queue<QueItem> q, QueItem item) | 304 | private void ThrottleCheck(ref PacketThrottle throttle, ref Queue<QueItem> q, QueItem item) |
@@ -372,9 +311,12 @@ namespace OpenSim.Region.ClientStack | |||
372 | 311 | ||
373 | if((q.Count == 0) && (throttle.UnderLimit())) | 312 | if((q.Count == 0) && (throttle.UnderLimit())) |
374 | { | 313 | { |
314 | Monitor.Enter(this); | ||
375 | throttle.Add(item.Packet.ToBytes().Length); | 315 | throttle.Add(item.Packet.ToBytes().Length); |
376 | TotalThrottle.Add(item.Packet.ToBytes().Length); | 316 | TotalThrottle.Add(item.Packet.ToBytes().Length); |
377 | SendQueue.Enqueue(item); | 317 | SendQueue.Enqueue(item); |
318 | Monitor.Pulse(this); | ||
319 | Monitor.Exit(this); | ||
378 | } | 320 | } |
379 | else | 321 | else |
380 | { | 322 | { |