From cde47c2b3d7089be556252246eb03365c1f39b54 Mon Sep 17 00:00:00 2001
From: John Hurliman
Date: Wed, 21 Oct 2009 00:18:35 -0700
Subject: Committing Jim's optimization to replace the 20ms sleep in outgoing
packet handling with an interruptible wait handle
---
.../Region/ClientStack/LindenUDP/LLUDPClient.cs | 51 +++++++++++++++-------
1 file changed, 35 insertions(+), 16 deletions(-)
(limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs')
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 134cfe5..b9d2c15 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -105,9 +105,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int TickLastPacketReceived;
/// Environment.TickCount of the last time the outgoing packet handler executed for this client
public int TickLastOutgoingPacketHandler;
+ /// Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler executed for this client
+ public int ElapsedMSOutgoingPacketHandler;
+ /// Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed for this client
+ public int Elapsed100MSOutgoingPacketHandler;
+ /// Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed for this client
+ public int Elapsed500MSOutgoingPacketHandler;
- /// Timer granularity. This is set to the measured resolution of Environment.TickCount
- public readonly float G;
/// Smoothed round-trip time. A smoothed average of the round-trip time for sending a
/// reliable packet to the client and receiving an ACK
public float SRTT;
@@ -182,15 +186,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type));
}
- // Set the granularity variable used for retransmission calculations to
- // the measured resolution of Environment.TickCount
- G = server.TickCountResolution;
-
// Default the retransmission timeout to three seconds
RTO = 3000;
// Initialize this to a sane value to prevent early disconnects
- TickLastPacketReceived = Environment.TickCount;
+ TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
+ ElapsedMSOutgoingPacketHandler = 0;
+ Elapsed100MSOutgoingPacketHandler = 0;
+ Elapsed500MSOutgoingPacketHandler = 0;
}
///
@@ -391,6 +394,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// Not enough tokens in the bucket, queue this packet
queue.Enqueue(packet);
+ m_udpServer.SignalOutgoingPacketHandler();
return true;
}
}
@@ -407,13 +411,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
/// This function is only called from a synchronous loop in the
/// UDPServer so we don't need to bother making this thread safe
- /// True if any packets were sent, otherwise false
- public bool DequeueOutgoing()
+ /// The minimum amount of time before the next packet
+ /// can be sent to this client
+ public int DequeueOutgoing()
{
OutgoingPacket packet;
OpenSim.Framework.LocklessQueue queue;
TokenBucket bucket;
- bool packetSent = false;
+ int dataLength;
+ int minTimeout = Int32.MaxValue;
//string queueDebugOutput = String.Empty; // Serious debug business
@@ -428,12 +434,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// leaving a dequeued packet still waiting to be sent out. Try to
// send it again
OutgoingPacket nextPacket = m_nextPackets[i];
- if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
+ dataLength = nextPacket.Buffer.DataLength;
+ if (bucket.RemoveTokens(dataLength))
{
// Send the packet
m_udpServer.SendPacketFinal(nextPacket);
m_nextPackets[i] = null;
- packetSent = true;
+ minTimeout = 0;
+ }
+ else if (minTimeout != 0)
+ {
+ // Check the minimum amount of time we would have to wait before this packet can be sent out
+ minTimeout = Math.Min(minTimeout, ((dataLength - bucket.Content) / bucket.DripPerMS) + 1);
}
}
else
@@ -445,16 +457,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// A packet was pulled off the queue. See if we have
// enough tokens in the bucket to send it out
- if (bucket.RemoveTokens(packet.Buffer.DataLength))
+ dataLength = packet.Buffer.DataLength;
+ if (bucket.RemoveTokens(dataLength))
{
// Send the packet
m_udpServer.SendPacketFinal(packet);
- packetSent = true;
+ minTimeout = 0;
}
else
{
// Save the dequeued packet for the next iteration
m_nextPackets[i] = packet;
+
+ if (minTimeout != 0)
+ {
+ // Check the minimum amount of time we would have to wait before this packet can be sent out
+ minTimeout = Math.Min(minTimeout, ((dataLength - bucket.Content) / bucket.DripPerMS) + 1);
+ }
}
// If the queue is empty after this dequeue, fire the queue
@@ -473,7 +492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
//m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
- return packetSent;
+ return minTimeout;
}
///
@@ -504,7 +523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
// Always round retransmission timeout up to two seconds
- RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR)));
+ RTO = Math.Max(2000, (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)));
//m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
// RTTVAR + " based on new RTT of " + r + "ms");
}
--
cgit v1.1