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