diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 630b6e69de..383eac036b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -347,10 +347,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected Dictionary m_groupPowers = new Dictionary(); protected int m_terrainCheckerCount; - // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet - protected int m_primTerseUpdatesPerPacket = 10; - protected int m_primFullUpdatesPerPacket = 14; - protected int m_avatarTerseUpdatesPerPacket = 5; + // These numbers are guesses at a decent tradeoff between responsiveness + // of the interest list and throughput. Lower is more responsive, higher + // is better throughput + protected int m_primTerseUpdatesPerPacket = 25; + protected int m_primFullUpdatesPerPacket = 100; + protected int m_avatarTerseUpdatesPerPacket = 10; /// Number of texture packets to put on the queue each time the /// OnQueueEmpty event is triggered for the texture category protected int m_textureSendLimit = 20; @@ -3415,33 +3417,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_avatarTerseUpdatesPerPacket; - if (max > m_avatarTerseUpdates.Count) - max = m_avatarTerseUpdates.Count; - - int count = 0; - int size = 0; - - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; - - Queue updates = new Queue(); - - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_avatarTerseUpdates.Peek().ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > Packet.MTU) - break; - size += length; - updates.Enqueue(m_avatarTerseUpdates.Dequeue()); - } + int count = Math.Min(m_avatarTerseUpdates.Count, m_avatarTerseUpdatesPerPacket); terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; - - for (int i = 0 ; i < count ; i++) - terse.ObjectData[i] = updates.Dequeue(); + for (int i = 0; i < count; i++) + terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue(); terse.Header.Reliable = false; terse.Header.Zerocoded = true; @@ -3656,34 +3636,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primFullUpdates.Count; - if (max > m_primFullUpdatesPerPacket) - max = m_primFullUpdatesPerPacket; + int count = Math.Min(m_primFullUpdates.Count, m_primFullUpdatesPerPacket); - int count = 0; - int size = 0; - - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; - - Queue updates = new Queue(); - - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_primFullUpdates.Peek().ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > Packet.MTU) - break; - size += length; - updates.Enqueue(m_primFullUpdates.Dequeue()); - } - - outPacket.ObjectData = - new ObjectUpdatePacket.ObjectDataBlock[count]; - - for (int index = 0 ; index < count ; index++) - outPacket.ObjectData[index] = updates.Dequeue(); + outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count]; + for (int i = 0; i < count; i++) + outPacket.ObjectData[i] = m_primFullUpdates.Dequeue(); outPacket.Header.Zerocoded = true; OutPacket(outPacket, ThrottleOutPacketType.State); @@ -3733,35 +3690,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primTerseUpdates.Count; - if (max > m_primTerseUpdatesPerPacket) - max = m_primTerseUpdatesPerPacket; + int count = Math.Min(m_primTerseUpdates.Count, m_primTerseUpdatesPerPacket); - int count = 0; - int size = 0; - - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; - - Queue updates = new Queue(); - - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_primTerseUpdates.Peek().ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > Packet.MTU) - break; - size += length; - updates.Enqueue(m_primTerseUpdates.Dequeue()); - } - - outPacket.ObjectData = - new ImprovedTerseObjectUpdatePacket. - ObjectDataBlock[count]; - - for (int index = 0 ; index < count ; index++) - outPacket.ObjectData[index] = updates.Dequeue(); + outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; + for (int i = 0; i < count; i++) + outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue(); outPacket.Header.Reliable = false; outPacket.Header.Zerocoded = true; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 8c42ca4358..9476eed5dc 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -297,14 +297,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Make sure none of the throttles are set below our packet MTU, // otherwise a throttle could become permanently clogged - resend = Math.Max(resend, Packet.MTU); - land = Math.Max(land, Packet.MTU); - wind = Math.Max(wind, Packet.MTU); - cloud = Math.Max(cloud, Packet.MTU); - task = Math.Max(task, Packet.MTU); - texture = Math.Max(texture, Packet.MTU); - asset = Math.Max(asset, Packet.MTU); - state = Math.Max(state, Packet.MTU); + resend = Math.Max(resend, LLUDPServer.MTU); + land = Math.Max(land, LLUDPServer.MTU); + wind = Math.Max(wind, LLUDPServer.MTU); + cloud = Math.Max(cloud, LLUDPServer.MTU); + task = Math.Max(task, LLUDPServer.MTU); + texture = Math.Max(texture, LLUDPServer.MTU); + asset = Math.Max(asset, LLUDPServer.MTU); + state = Math.Max(state, LLUDPServer.MTU); int total = resend + land + wind + cloud + task + texture + asset + state; @@ -404,9 +404,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP TokenBucket bucket; bool packetSent = false; + //string queueDebugOutput = String.Empty; // Serious debug business + for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) { bucket = m_throttleCategories[i]; + //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business if (m_nextPackets[i] != null) { @@ -458,6 +461,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business return packetSent; } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index b11a80dd23..f2b8720f95 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -89,6 +89,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public class LLUDPServer : OpenSimUDPBase { + /// Maximum transmission unit, or UDP packet size, for the LLUDP protocol + public const int MTU = 1400; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// Handlers for incoming packets @@ -272,7 +275,7 @@ 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) ? Packet.MTU : 200; + int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); @@ -569,9 +572,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // client.BytesSinceLastACK. Lockless thread safety int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); bytesSinceLastACK += buffer.DataLength; - if (bytesSinceLastACK > Packet.MTU * 2) + if (bytesSinceLastACK > LLUDPServer.MTU * 2) { - bytesSinceLastACK -= Packet.MTU * 2; + bytesSinceLastACK -= LLUDPServer.MTU * 2; SendAcks(udpClient); } Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);