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.
0.6.0-stable
Sean Dague 2008-06-04 17:43:07 +00:00
parent 6e2f3bd3fb
commit 0cacdd370c
1 changed files with 45 additions and 35 deletions

View File

@ -26,6 +26,7 @@
*/ */
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@ -44,7 +45,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>(); protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
//public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
public Hashtable clientCircuits_reverse = Hashtable.Synchronized(new Hashtable());
protected Dictionary<uint, EndPoint> proxyCircuits = new Dictionary<uint, EndPoint>(); protected Dictionary<uint, EndPoint> proxyCircuits = new Dictionary<uint, EndPoint>();
private Socket m_socket; private Socket m_socket;
protected IPEndPoint ServerIncoming; protected IPEndPoint ServerIncoming;
@ -379,13 +383,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
else else
m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
} }
lock (clientCircuits_reverse)
{ // This doesn't need locking as it's synchronized data
if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender); clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender);
else else
m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
}
lock (proxyCircuits) lock (proxyCircuits)
{ {
@ -437,22 +441,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
// find the endpoint for this circuit // find the endpoint for this circuit
EndPoint sendto = null; 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 //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString());
if (proxyPortOffset != 0) PacketPool.EncodeProxyMessage(buffer, ref size, sendto);
{ m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]);
//MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString()); }
PacketPool.EncodeProxyMessage(buffer, ref size, sendto); else
m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]); {
} //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString());
else m_socket.SendTo(buffer, size, flags, sendto);
{
//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) public virtual void RemoveClientCircuit(uint circuitcode)
{ {
EndPoint sendto = null; EndPoint sendto = null;
lock (clientCircuits_reverse) if (clientCircuits_reverse.Contains(circuitcode)) {
{ sendto = (EndPoint)clientCircuits_reverse[circuitcode];
if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
{
clientCircuits.Remove(sendto);
clientCircuits_reverse.Remove(circuitcode); clientCircuits_reverse.Remove(circuitcode);
lock(clientCircuits) {
clientCircuits.Remove(sendto);
}
lock(proxyCircuits) {
proxyCircuits.Remove(circuitcode); proxyCircuits.Remove(circuitcode);
} }
} }
@ -488,13 +499,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
else else
m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
} }
lock (clientCircuits_reverse)
{ // This data structure is synchronized, so we don't need the lock
if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP); clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP);
else else
m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
}
lock (proxyCircuits) lock (proxyCircuits)
{ {