aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDr Scofield2009-06-25 07:59:25 +0000
committerDr Scofield2009-06-25 07:59:25 +0000
commit77122d78618e6545c7600504182ac61ed07bef59 (patch)
tree2e5af07e280c0f928f60f3352480aa31619cf127
parentadding logging statement for receive buffer size (diff)
downloadopensim-SC-77122d78618e6545c7600504182ac61ed07bef59.zip
opensim-SC-77122d78618e6545c7600504182ac61ed07bef59.tar.gz
opensim-SC-77122d78618e6545c7600504182ac61ed07bef59.tar.bz2
opensim-SC-77122d78618e6545c7600504182ac61ed07bef59.tar.xz
more efficient way of checking for already seen packets:
- uses Environment.TickCount for all timestamps (instead of more costly Util.UnixTimeSinceEpoch() - takes care of Environment.TickCount overflow (which will happens after 24.8 days of system uptime) - avoids instantiating List copies for each check - gets rid of one lock() invocation - moves calculation of loop invariant variable out of the loop itself
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs76
1 files changed, 47 insertions, 29 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
index a7c931e..39922c0 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
@@ -90,10 +90,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
90 // the hashing. Expiration is less common and can be allowed the 90 // the hashing. Expiration is less common and can be allowed the
91 // time for a linear scan. 91 // time for a linear scan.
92 // 92 //
93 private Dictionary<uint, int> m_DupeTracker = 93 private List<uint> m_alreadySeenList = new List<uint>();
94 new Dictionary<uint, int>(); 94 private Dictionary<uint, int>m_alreadySeenTracker = new Dictionary<uint, int>();
95 private uint m_DupeTrackerWindow = 30; 95 private int m_alreadySeenWindow = 30000;
96 private int m_DupeTrackerLastCheck = Environment.TickCount; 96 private int m_lastAlreadySeenCheck = Environment.TickCount & Int32.MaxValue;
97
98 // private Dictionary<uint, int> m_DupeTracker =
99 // new Dictionary<uint, int>();
100 // private uint m_DupeTrackerWindow = 30;
101 // private int m_DupeTrackerLastCheck = Environment.TickCount;
97 102
98 // Values for the SimStatsReporter 103 // Values for the SimStatsReporter
99 // 104 //
@@ -449,27 +454,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
449 // We can't keep an unlimited record of dupes. This will prune the 454 // We can't keep an unlimited record of dupes. This will prune the
450 // dictionary by age. 455 // dictionary by age.
451 // 456 //
452 private void PruneDupeTracker() 457 // NOTE: this needs to be called from within lock
458 // (m_alreadySeenTracker) context!
459 private void ExpireSeenPackets()
453 { 460 {
454 lock (m_DupeTracker) 461 if (m_alreadySeenList.Count < 1024)
462 return;
463
464 int ticks = 0;
465 int tc = Environment.TickCount & Int32.MaxValue;
466 if (tc >= m_lastAlreadySeenCheck)
467 ticks = tc - m_lastAlreadySeenCheck;
468 else
469 ticks = Int32.MaxValue - m_lastAlreadySeenCheck + tc;
470
471 if (ticks < 2000) return;
472 m_lastAlreadySeenCheck = tc;
473
474 // we calculate the drop dead tick count here instead of
475 // in the loop: any packet with a timestamp before
476 // dropDeadTC can be expired
477 int dropDeadTC = tc - m_alreadySeenWindow;
478 int i = 0;
479 while (i < m_alreadySeenList.Count && m_alreadySeenTracker[m_alreadySeenList[i]] < dropDeadTC)
455 { 480 {
456 if (m_DupeTracker.Count < 1024) 481 m_alreadySeenTracker.Remove(m_alreadySeenList[i]);
457 return; 482 i++;
458 483 }
459 if (Environment.TickCount - m_DupeTrackerLastCheck < 2000) 484 // if we dropped packet from m_alreadySeenTracker we need
460 return; 485 // to drop them from m_alreadySeenList as well, let's do
461 486 // that in one go: the list is ordered after all.
462 m_DupeTrackerLastCheck = Environment.TickCount; 487 if (i > 0)
463 488 {
464 Dictionary<uint, int> packs = 489 m_alreadySeenList.RemoveRange(0, i);
465 new Dictionary<uint, int>(m_DupeTracker); 490 // m_log.DebugFormat("[CLIENT]: expired {0} packets, {1}:{2} left", i, m_alreadySeenList.Count, m_alreadySeenTracker.Count);
466
467 foreach (uint pack in packs.Keys)
468 {
469 if (Util.UnixTimeSinceEpoch() - m_DupeTracker[pack] >
470 m_DupeTrackerWindow)
471 m_DupeTracker.Remove(pack);
472 }
473 } 491 }
474 } 492 }
475 493
@@ -545,18 +563,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
545 if (packet.Type != PacketType.AgentUpdate) 563 if (packet.Type != PacketType.AgentUpdate)
546 m_PacketsReceived++; 564 m_PacketsReceived++;
547 565
548 PruneDupeTracker();
549
550 // Check for duplicate packets.. packets that the client is 566 // Check for duplicate packets.. packets that the client is
551 // resending because it didn't receive our ack 567 // resending because it didn't receive our ack
552 // 568 //
553 lock (m_DupeTracker) 569 lock (m_alreadySeenTracker)
554 { 570 {
555 if (m_DupeTracker.ContainsKey(packet.Header.Sequence)) 571 ExpireSeenPackets();
572
573 if (m_alreadySeenTracker.ContainsKey(packet.Header.Sequence))
556 return; 574 return;
557 575
558 m_DupeTracker.Add(packet.Header.Sequence, 576 m_alreadySeenTracker.Add(packet.Header.Sequence, Environment.TickCount & Int32.MaxValue);
559 Util.UnixTimeSinceEpoch()); 577 m_alreadySeenList.Add(packet.Header.Sequence);
560 } 578 }
561 579
562 m_Client.ProcessInPacket(packet); 580 m_Client.ProcessInPacket(packet);