mirror of
https://github.com/opensim/opensim.git
synced 2026-08-04 16:22:50 +08:00
change UDPPacketBuffer pools (does waste a bit of memory)
This commit is contained in:
@@ -344,18 +344,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
|
||||
protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
|
||||
|
||||
protected Pool<IncomingPacket> m_incomingPacketPool;
|
||||
|
||||
/// <summary>
|
||||
/// Stat for number of packets in the main pool awaiting use.
|
||||
/// </summary>
|
||||
protected Stat m_poolCountStat;
|
||||
|
||||
/// <summary>
|
||||
/// Stat for number of packets in the inbound packet pool awaiting use.
|
||||
/// </summary>
|
||||
protected Stat m_incomingPacketPoolStat;
|
||||
|
||||
protected int m_defaultRTO = 0;
|
||||
protected int m_maxRTO = 0;
|
||||
protected int m_ackTimeout = 0;
|
||||
@@ -498,7 +486,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
|
||||
// if (usePools)
|
||||
// EnablePools();
|
||||
base.DisablePools();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
@@ -554,83 +541,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
OqrEngine.Stop();
|
||||
}
|
||||
|
||||
public override bool EnablePools()
|
||||
{
|
||||
if (!UsePools)
|
||||
{
|
||||
base.EnablePools();
|
||||
|
||||
m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool DisablePools()
|
||||
{
|
||||
if (UsePools)
|
||||
{
|
||||
base.DisablePools();
|
||||
|
||||
StatsManager.DeregisterStat(m_incomingPacketPoolStat);
|
||||
|
||||
// We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
|
||||
/// stats.
|
||||
/// </summary>
|
||||
protected internal void EnablePoolStats()
|
||||
{
|
||||
m_poolCountStat
|
||||
= new Stat(
|
||||
"UDPPacketBufferPoolCount",
|
||||
"Objects within the UDPPacketBuffer pool",
|
||||
"The number of objects currently stored within the UDPPacketBuffer pool",
|
||||
"",
|
||||
"clientstack",
|
||||
Scene.Name,
|
||||
StatType.Pull,
|
||||
stat => stat.Value = Pool.Count,
|
||||
StatVerbosity.Debug);
|
||||
|
||||
StatsManager.RegisterStat(m_poolCountStat);
|
||||
|
||||
m_incomingPacketPoolStat
|
||||
= new Stat(
|
||||
"IncomingPacketPoolCount",
|
||||
"Objects within incoming packet pool",
|
||||
"The number of objects currently stored within the incoming packet pool",
|
||||
"",
|
||||
"clientstack",
|
||||
Scene.Name,
|
||||
StatType.Pull,
|
||||
stat => stat.Value = m_incomingPacketPool.Count,
|
||||
StatVerbosity.Debug);
|
||||
|
||||
StatsManager.RegisterStat(m_incomingPacketPoolStat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables pool stats.
|
||||
/// </summary>
|
||||
protected internal void DisablePoolStats()
|
||||
{
|
||||
StatsManager.DeregisterStat(m_poolCountStat);
|
||||
m_poolCountStat = null;
|
||||
|
||||
StatsManager.DeregisterStat(m_incomingPacketPoolStat);
|
||||
m_incomingPacketPoolStat = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
|
||||
/// </summary>
|
||||
@@ -658,8 +568,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name),
|
||||
"INCOMING PACKET ASYNC HANDLING ENGINE");
|
||||
*/
|
||||
OqrEngine
|
||||
= new JobEngine(
|
||||
OqrEngine = new JobEngine(
|
||||
string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
|
||||
"OUTGOING QUEUE REFILL ENGINE");
|
||||
|
||||
@@ -769,15 +678,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
stat => stat.Value = OqrEngine.JobsWaiting,
|
||||
StatVerbosity.Debug));
|
||||
|
||||
// We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by
|
||||
// scene name
|
||||
if (UsePools)
|
||||
EnablePoolStats();
|
||||
|
||||
StatsManager.RegisterStat(
|
||||
new Stat(
|
||||
"UDPBuffersPoolCount",
|
||||
"Buffers in the UDP buffers pool",
|
||||
"The number of buffers currently stored within the UDP buffers pool",
|
||||
"",
|
||||
"clientstack",
|
||||
Scene.Name,
|
||||
StatType.Pull,
|
||||
stat => stat.Value = m_udpBuffersPoolPtr,
|
||||
StatVerbosity.Debug));
|
||||
|
||||
LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
|
||||
commands.Register();
|
||||
|
||||
}
|
||||
|
||||
public bool HandlesRegion(Location x)
|
||||
@@ -939,9 +853,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
// The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
|
||||
// there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
|
||||
// to accomodate for both common scenarios and provide ample room for ACK appending in both
|
||||
int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
|
||||
//int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
|
||||
|
||||
UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
|
||||
//UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
|
||||
UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
|
||||
|
||||
// Zerocode if needed
|
||||
if (doZerocode)
|
||||
@@ -971,7 +886,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
// If the packet data wasn't already copied during zerocoding, copy it now
|
||||
if (doCopy)
|
||||
{
|
||||
if (dataLength <= buffer.Data.Length)
|
||||
//if (dataLength <= buffer.Data.Length)
|
||||
if (dataLength <= LLUDPServer.MTU)
|
||||
{
|
||||
Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
|
||||
}
|
||||
@@ -979,7 +895,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
{
|
||||
m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
|
||||
type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
|
||||
buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength);
|
||||
// buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength);
|
||||
buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
|
||||
Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
|
||||
}
|
||||
}
|
||||
@@ -1168,22 +1085,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
// Set the appended ACKs flag on this packet
|
||||
buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
|
||||
}
|
||||
buffer.DataLength = dataLength;
|
||||
}
|
||||
|
||||
buffer.DataLength = dataLength;
|
||||
|
||||
if (!isResend)
|
||||
{
|
||||
// Not a resend, assign a new sequence number
|
||||
uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
|
||||
Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
|
||||
outgoingPacket.SequenceNumber = sequenceNumber;
|
||||
|
||||
if (isReliable)
|
||||
{
|
||||
// Add this packet to the list of ACK responses we are waiting on from the server
|
||||
udpClient.NeedAcks.Add(outgoingPacket);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1196,9 +1106,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
PacketsSentCount++;
|
||||
|
||||
SyncSend(buffer);
|
||||
|
||||
// Keep track of when this packet was sent out (right now)
|
||||
outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
|
||||
|
||||
if (outgoingPacket.UnackedMethod == null)
|
||||
FreeUDPBuffer(buffer);
|
||||
else if(!isResend)
|
||||
{
|
||||
// Add this packet to the list of ACK responses we are waiting on from the server
|
||||
udpClient.NeedAcks.Add(outgoingPacket);
|
||||
}
|
||||
|
||||
if (udpClient.DebugDataOutLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}",
|
||||
@@ -1240,7 +1159,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
||||
|
||||
RecordMalformedInboundPacket(endPoint);
|
||||
|
||||
FreeUDPBuffer(buffer);
|
||||
return; // Drop undersized packet
|
||||
}
|
||||
|
||||
@@ -1260,21 +1179,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
||||
|
||||
RecordMalformedInboundPacket(endPoint);
|
||||
|
||||
FreeUDPBuffer(buffer);
|
||||
return; // Malformed header
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
|
||||
// // Only allocate a buffer for zerodecoding if the packet is zerocoded
|
||||
// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
|
||||
packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
|
||||
// Only allocate a buffer for zerodecoding if the packet is zerocoded
|
||||
((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
|
||||
// If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
|
||||
// assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
|
||||
// bytes are copied out).
|
||||
packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
|
||||
// packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
|
||||
// Only allocate a buffer for zerodecoding if the packet is zerocoded
|
||||
((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
|
||||
// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -1292,7 +1211,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
}
|
||||
|
||||
RecordMalformedInboundPacket(endPoint);
|
||||
|
||||
FreeUDPBuffer(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1311,17 +1230,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
lock (m_pendingCache)
|
||||
{
|
||||
if (m_pendingCache.Contains(endPoint))
|
||||
{
|
||||
FreeUDPBuffer(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
|
||||
}
|
||||
|
||||
// We need to copy the endpoint so that it doesn't get changed when another thread reuses the
|
||||
// buffer.
|
||||
object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
|
||||
|
||||
Util.FireAndForget(HandleUseCircuitCode, array);
|
||||
|
||||
Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet });
|
||||
FreeUDPBuffer(buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1336,24 +1254,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
queue.Enqueue(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
else if (packet.Type == PacketType.CompleteAgentMovement)
|
||||
{
|
||||
// Send ack straight away to let the viewer know that we got it.
|
||||
SendAckImmediate(endPoint, packet.Header.Sequence);
|
||||
|
||||
// We need to copy the endpoint so that it doesn't get changed when another thread reuses the
|
||||
// buffer.
|
||||
object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
|
||||
|
||||
Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
|
||||
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
FreeUDPBuffer(buffer);
|
||||
|
||||
// Determine which agent this packet came from
|
||||
if (client == null || !(client is LLClientView))
|
||||
{
|
||||
@@ -1471,10 +1375,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
|
||||
#endregion BinaryStats
|
||||
|
||||
|
||||
//AgentUpdate removed from here
|
||||
|
||||
|
||||
#region Ping Check Handling
|
||||
|
||||
if (packet.Type == PacketType.StartPingCheck)
|
||||
@@ -1506,17 +1406,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
|
||||
IncomingPacket incomingPacket;
|
||||
|
||||
// Inbox insertion
|
||||
if (UsePools)
|
||||
{
|
||||
incomingPacket = m_incomingPacketPool.GetObject();
|
||||
incomingPacket.Client = (LLClientView)client;
|
||||
incomingPacket.Packet = packet;
|
||||
}
|
||||
else
|
||||
{
|
||||
incomingPacket = new IncomingPacket((LLClientView)client, packet);
|
||||
}
|
||||
incomingPacket = new IncomingPacket((LLClientView)client, packet);
|
||||
|
||||
// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
|
||||
// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
|
||||
@@ -1525,7 +1415,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
// else
|
||||
// packetInbox.Enqueue(incomingPacket);
|
||||
packetInbox.Add(incomingPacket);
|
||||
|
||||
}
|
||||
|
||||
#region BinaryStats
|
||||
@@ -1881,13 +1770,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
byte[] packetData = ack.ToBytes();
|
||||
int length = packetData.Length;
|
||||
|
||||
UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);
|
||||
UDPPacketBuffer buffer = GetNewUDPBuffer(remoteEndpoint);
|
||||
buffer.DataLength = length;
|
||||
|
||||
Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
|
||||
|
||||
// AsyncBeginSend(buffer);
|
||||
SyncSend(buffer);
|
||||
FreeUDPBuffer(buffer);
|
||||
}
|
||||
|
||||
protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
|
||||
@@ -1982,17 +1872,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
Scene.ThreadAlive(1);
|
||||
try
|
||||
{
|
||||
packetInbox.TryTake(out incomingPacket, 250);
|
||||
packetInbox.TryTake(out incomingPacket, 4500);
|
||||
|
||||
if (incomingPacket != null && IsRunningInbound)
|
||||
{
|
||||
ProcessInPacket(incomingPacket);
|
||||
|
||||
if (UsePools)
|
||||
{
|
||||
incomingPacket.Client = null;
|
||||
m_incomingPacketPool.ReturnObject(incomingPacket);
|
||||
}
|
||||
incomingPacket = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user