From d38f33736c371cf8c09d78ee5c42b8cc943bb1d7 Mon Sep 17 00:00:00 2001
From: John Hurliman
Date: Tue, 20 Oct 2009 14:41:20 -0700
Subject: * Removed the throttle speed optimizations to see if it brings
stability back * Changed the outgoing packet handler to use a real function
instead of a closure and to track time on a per-client basis instead of a
global basis
---
.../Region/ClientStack/LindenUDP/LLUDPClient.cs | 25 +++--
.../Region/ClientStack/LindenUDP/LLUDPServer.cs | 116 ++++++++++-----------
2 files changed, 69 insertions(+), 72 deletions(-)
(limited to 'OpenSim/Region/ClientStack')
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 4a3a04e..ec74188 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -101,6 +101,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public bool IsPaused = true;
/// Environment.TickCount when the last packet was received for this client
public int TickLastPacketReceived;
+ /// Environment.TickCount of the last time the outgoing packet handler executed for this client
+ public int TickLastOutgoingPacketHandler;
/// Timer granularity. This is set to the measured resolution of Environment.TickCount
public readonly float G;
@@ -320,27 +322,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
bucket.MaxBurst = total;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
- bucket.DripRate = bucket.MaxBurst = resend;
+ bucket.DripRate = resend;
+ bucket.MaxBurst = resend;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
- bucket.DripRate = bucket.MaxBurst = land;
+ bucket.DripRate = land;
+ bucket.MaxBurst = land;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
- bucket.DripRate = bucket.MaxBurst = wind;
+ bucket.DripRate = wind;
+ bucket.MaxBurst = wind;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
- bucket.DripRate = bucket.MaxBurst = cloud;
+ bucket.DripRate = cloud;
+ bucket.MaxBurst = cloud;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
- bucket.DripRate = bucket.MaxBurst = asset;
+ bucket.DripRate = asset;
+ bucket.MaxBurst = asset;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
- bucket.DripRate = task + state + texture;
- bucket.MaxBurst = task + state + texture;
+ bucket.DripRate = task + state;
+ bucket.MaxBurst = task + state;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
- bucket.DripRate = state + texture;
- bucket.MaxBurst = state + texture;
+ bucket.DripRate = state;
+ bucket.MaxBurst = state;
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
bucket.DripRate = texture;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 3881bdb..80ef95e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -118,6 +118,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_recvBufferSize;
/// Flag to process packets asynchronously or synchronously
private bool m_asyncPacketHandling;
+ /// Track whether or not a packet was sent in the
+ /// OutgoingPacketHandler loop so we know when to sleep
+ private bool m_packetSentLastLoop;
/// The measured resolution of Environment.TickCount
public float TickCountResolution { get { return m_tickCountResolution; } }
@@ -745,10 +748,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
while (base.IsRunning)
{
- IncomingPacket incomingPacket = null;
-
try
{
+ IncomingPacket incomingPacket = null;
+
if (packetInbox.Dequeue(100, ref incomingPacket))
Util.FireAndForget(ProcessInPacket, incomingPacket);
}
@@ -769,83 +772,70 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// on to en-US to avoid number parsing issues
Culture.SetCurrentCulture();
- int now = Environment.TickCount;
- int elapsedMS = 0;
- int elapsed100MS = 0;
- int elapsed500MS = 0;
-
while (base.IsRunning)
{
try
{
- bool resendUnacked = false;
- bool sendAcks = false;
- bool sendPings = false;
- bool packetSent = false;
+ m_packetSentLastLoop = false;
- elapsedMS += Environment.TickCount - now;
+ m_scene.ClientManager.ForEachSync(ClientOutgoingPacketHandler);
- // Check for pending outgoing resends every 100ms
- if (elapsedMS >= 100)
- {
- resendUnacked = true;
- elapsedMS -= 100;
- ++elapsed100MS;
- }
- // Check for pending outgoing ACKs every 500ms
- if (elapsed100MS >= 5)
- {
- sendAcks = true;
- elapsed100MS = 0;
- ++elapsed500MS;
- }
- // Send pings to clients every 5000ms
- if (elapsed500MS >= 10)
- {
- sendPings = true;
- elapsed500MS = 0;
- }
+ // If no packets at all were sent, sleep to avoid chewing up CPU cycles
+ // when there is nothing to do
+ if (!m_packetSentLastLoop)
+ Thread.Sleep(20);
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
+ }
+ }
+ }
- m_scene.ClientManager.ForEachSync(
- delegate(IClientAPI client)
+ private void ClientOutgoingPacketHandler(IClientAPI client)
+ {
+ try
+ {
+ if (client is LLClientView)
+ {
+ LLUDPClient udpClient = ((LLClientView)client).UDPClient;
+
+ int thisTick = Environment.TickCount & Int32.MaxValue;
+ int elapsedMS = thisTick - udpClient.TickLastOutgoingPacketHandler;
+
+ if (udpClient.IsConnected)
+ {
+ // Check for pending outgoing resends every 100ms
+ if (elapsedMS >= 100)
{
- try
+ ResendUnacked(udpClient);
+
+ // Check for pending outgoing ACKs every 500ms
+ if (elapsedMS >= 500)
{
- if (client is LLClientView)
+ SendAcks(udpClient);
+
+ // Send pings to clients every 5000ms
+ if (elapsedMS >= 5000)
{
- LLUDPClient udpClient = ((LLClientView)client).UDPClient;
-
- if (udpClient.IsConnected)
- {
- if (udpClient.DequeueOutgoing())
- packetSent = true;
- if (resendUnacked)
- ResendUnacked(udpClient);
- if (sendAcks)
- {
- SendAcks(udpClient);
- udpClient.SendPacketStats();
- }
- if (sendPings)
- SendPing(udpClient);
- }
+ SendPing(udpClient);
}
}
- catch (Exception ex)
- {
- m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + " threw an exception: " + ex.Message, ex);
- }
}
- );
- if (!packetSent)
- Thread.Sleep(20);
- }
- catch (Exception ex)
- {
- m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
+ // Dequeue any outgoing packets that are within the throttle limits
+ if (udpClient.DequeueOutgoing())
+ m_packetSentLastLoop = true;
+ }
+
+ udpClient.TickLastOutgoingPacketHandler = thisTick;
}
}
+ catch (Exception ex)
+ {
+ m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
+ " threw an exception: " + ex.Message, ex);
+ }
}
private void ProcessInPacket(object state)
--
cgit v1.1