diff options
author | Dr Scofield | 2009-06-25 07:59:25 +0000 |
---|---|---|
committer | Dr Scofield | 2009-06-25 07:59:25 +0000 |
commit | 77122d78618e6545c7600504182ac61ed07bef59 (patch) | |
tree | 2e5af07e280c0f928f60f3352480aa31619cf127 /OpenSim | |
parent | adding logging statement for receive buffer size (diff) | |
download | opensim-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
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs | 76 |
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); |