From 0cacdd370c75fbfbc7d90369c2aec17fe0991387 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Wed, 4 Jun 2008 17:43:07 +0000 Subject: change clientCircuits_reverse to a synchronized hash table. This removes a lock on every SendPacketTo call, which was shown to have good performance benefits by the IBM China Research Lab. --- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 80 ++++++++++++---------- 1 file changed, 45 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region/ClientStack/LindenUDP') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index fcb611f..53e92ae 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; @@ -44,7 +45,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Dictionary clientCircuits = new Dictionary(); - public Dictionary clientCircuits_reverse = new Dictionary(); + + //public Dictionary clientCircuits_reverse = new Dictionary(); + public Hashtable clientCircuits_reverse = Hashtable.Synchronized(new Hashtable()); + protected Dictionary proxyCircuits = new Dictionary(); private Socket m_socket; protected IPEndPoint ServerIncoming; @@ -379,13 +383,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP else m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); } - lock (clientCircuits_reverse) - { - if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) - clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender); - else - m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); - } + + // This doesn't need locking as it's synchronized data + if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) + clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender); + else + m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); + lock (proxyCircuits) { @@ -437,22 +441,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // find the endpoint for this circuit EndPoint sendto = null; - lock (clientCircuits_reverse) + try { + sendto = (EndPoint)clientCircuits_reverse[circuitcode]; + } catch { + // Exceptions here mean there is no circuit + m_log.Warn("Circuit not found, not sending packet"); + return; + } + + if (sendto != null) { - if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto)) + //we found the endpoint so send the packet to it + if (proxyPortOffset != 0) { - //we found the endpoint so send the packet to it - if (proxyPortOffset != 0) - { - //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString()); - PacketPool.EncodeProxyMessage(buffer, ref size, sendto); - m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]); - } - else - { - //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString()); - m_socket.SendTo(buffer, size, flags, sendto); - } + //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString()); + PacketPool.EncodeProxyMessage(buffer, ref size, sendto); + m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]); + } + else + { + //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString()); + m_socket.SendTo(buffer, size, flags, sendto); } } } @@ -460,13 +469,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void RemoveClientCircuit(uint circuitcode) { EndPoint sendto = null; - lock (clientCircuits_reverse) - { - if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto)) - { - clientCircuits.Remove(sendto); + if (clientCircuits_reverse.Contains(circuitcode)) { + sendto = (EndPoint)clientCircuits_reverse[circuitcode]; - clientCircuits_reverse.Remove(circuitcode); + clientCircuits_reverse.Remove(circuitcode); + + lock(clientCircuits) { + clientCircuits.Remove(sendto); + } + lock(proxyCircuits) { proxyCircuits.Remove(circuitcode); } } @@ -488,13 +499,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP else m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); } - lock (clientCircuits_reverse) - { - if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) - clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP); - else - m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); - } + + // This data structure is synchronized, so we don't need the lock + if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) + clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP); + else + m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); lock (proxyCircuits) { -- cgit v1.1