From b402220dbb4e2f1c936ede1498a106ca5fd2f106 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 18 Jul 2013 00:30:22 +0100 Subject: [PATCH] Put in temporary hack for performnace 'queue-empty' logic on a persistent thread rather than through fire and forget May not scale since this gives each client its own thread. --- .../ClientStack/Linden/UDP/LLUDPClient.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 7749446f52..daed99a41f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -31,6 +31,7 @@ using System.Net; using System.Threading; using log4net; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenMetaverse; using OpenMetaverse.Packets; @@ -141,6 +142,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP get { return m_throttleClient; } } + private AutoResetEvent m_queueEmptyEvent = new AutoResetEvent(false); + /// Throttle bucket for this agent's connection private readonly TokenBucket m_throttleCategory; /// Throttle buckets for each packet category @@ -213,6 +216,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Initialize this to a sane value to prevent early disconnects TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; + + Watchdog.StartThread( + ActOnEmptyQueue, string.Format("ActOnEmptyQueue {0}", AgentID), ThreadPriority.Normal, false, false); + } + + private void ActOnEmptyQueue() + { + while (true) + { + m_queueEmptyEvent.WaitOne(); + FireQueueEmpty(m_categories); + Watchdog.UpdateThread(); + } } /// @@ -546,7 +562,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (emptyCategories != 0) + { BeginFireQueueEmpty(emptyCategories); + } //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business return packetSent; @@ -606,6 +624,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP RTO = Math.Min(RTO * 2, m_maxRTO); } + private ThrottleOutPacketTypeFlags m_categories = 0; + /// /// Does an early check to see if this queue empty callback is already /// running, then asynchronously firing the event @@ -617,9 +637,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // Use a value of 0 to signal that FireQueueEmpty is running m_nextOnQueueEmpty = 0; + m_categories = categories; + m_queueEmptyEvent.Set(); // Asynchronously run the callback - Util.FireAndForget(FireQueueEmpty, categories); + //Util.FireAndForget(FireQueueEmpty, categories); } + +// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) +// { +// // Use a value of 0 to signal that FireQueueEmpty is running +// m_nextOnQueueEmpty = 0; +// // Asynchronously run the callback +// Util.FireAndForget(FireQueueEmpty, categories); +// } } /// @@ -631,6 +661,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// signature private void FireQueueEmpty(object o) { +// m_log.DebugFormat("[LLUDPCLIENT]: Firing outbound UDP queue empty for {0}", AgentID); + const int MIN_CALLBACK_MS = 30; ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;