* Simplified the prioritization packet creation code to reduce CPU usage and increase throughput. Apologies to Jim for hacking on your code while it's only halfway done, I'll take responsibility for the manual merge

* Changed LLUDP to use its own MTU value of 1400 instead of the 1200 value pulled from the currently shipped libomv
prioritization
John Hurliman 2009-10-16 14:17:13 -07:00
parent b813058635
commit 1bd9202f24
3 changed files with 35 additions and 95 deletions

View File

@ -347,10 +347,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>();
protected int m_terrainCheckerCount; protected int m_terrainCheckerCount;
// LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet // These numbers are guesses at a decent tradeoff between responsiveness
protected int m_primTerseUpdatesPerPacket = 10; // of the interest list and throughput. Lower is more responsive, higher
protected int m_primFullUpdatesPerPacket = 14; // is better throughput
protected int m_avatarTerseUpdatesPerPacket = 5; protected int m_primTerseUpdatesPerPacket = 25;
protected int m_primFullUpdatesPerPacket = 100;
protected int m_avatarTerseUpdatesPerPacket = 10;
/// <summary>Number of texture packets to put on the queue each time the /// <summary>Number of texture packets to put on the queue each time the
/// OnQueueEmpty event is triggered for the texture category</summary> /// OnQueueEmpty event is triggered for the texture category</summary>
protected int m_textureSendLimit = 20; protected int m_textureSendLimit = 20;
@ -3415,33 +3417,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
terse.RegionData.TimeDilation = terse.RegionData.TimeDilation =
(ushort)(Scene.TimeDilation * ushort.MaxValue); (ushort)(Scene.TimeDilation * ushort.MaxValue);
int max = m_avatarTerseUpdatesPerPacket; int count = Math.Min(m_avatarTerseUpdates.Count, 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<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> updates = new Queue<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
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());
}
terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
terse.ObjectData[i] = updates.Dequeue(); terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
terse.Header.Reliable = false; terse.Header.Reliable = false;
terse.Header.Zerocoded = true; terse.Header.Zerocoded = true;
@ -3656,34 +3636,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
outPacket.RegionData.TimeDilation = outPacket.RegionData.TimeDilation =
(ushort)(Scene.TimeDilation * ushort.MaxValue); (ushort)(Scene.TimeDilation * ushort.MaxValue);
int max = m_primFullUpdates.Count; int count = Math.Min(m_primFullUpdates.Count, m_primFullUpdatesPerPacket);
if (max > m_primFullUpdatesPerPacket)
max = m_primFullUpdatesPerPacket;
int count = 0; outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count];
int size = 0; for (int i = 0; i < count; i++)
outPacket.ObjectData[i] = m_primFullUpdates.Dequeue();
byte[] zerobuffer = new byte[1024];
byte[] blockbuffer = new byte[1024];
Queue<ObjectUpdatePacket.ObjectDataBlock> updates = new Queue<ObjectUpdatePacket.ObjectDataBlock>();
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.Header.Zerocoded = true; outPacket.Header.Zerocoded = true;
OutPacket(outPacket, ThrottleOutPacketType.State); OutPacket(outPacket, ThrottleOutPacketType.State);
@ -3733,35 +3690,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
outPacket.RegionData.TimeDilation = outPacket.RegionData.TimeDilation =
(ushort)(Scene.TimeDilation * ushort.MaxValue); (ushort)(Scene.TimeDilation * ushort.MaxValue);
int max = m_primTerseUpdates.Count; int count = Math.Min(m_primTerseUpdates.Count, m_primTerseUpdatesPerPacket);
if (max > m_primTerseUpdatesPerPacket)
max = m_primTerseUpdatesPerPacket;
int count = 0; outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
int size = 0; for (int i = 0; i < count; i++)
outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
byte[] zerobuffer = new byte[1024];
byte[] blockbuffer = new byte[1024];
Queue<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> updates = new Queue<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
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.Header.Reliable = false; outPacket.Header.Reliable = false;
outPacket.Header.Zerocoded = true; outPacket.Header.Zerocoded = true;

View File

@ -297,14 +297,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Make sure none of the throttles are set below our packet MTU, // Make sure none of the throttles are set below our packet MTU,
// otherwise a throttle could become permanently clogged // otherwise a throttle could become permanently clogged
resend = Math.Max(resend, Packet.MTU); resend = Math.Max(resend, LLUDPServer.MTU);
land = Math.Max(land, Packet.MTU); land = Math.Max(land, LLUDPServer.MTU);
wind = Math.Max(wind, Packet.MTU); wind = Math.Max(wind, LLUDPServer.MTU);
cloud = Math.Max(cloud, Packet.MTU); cloud = Math.Max(cloud, LLUDPServer.MTU);
task = Math.Max(task, Packet.MTU); task = Math.Max(task, LLUDPServer.MTU);
texture = Math.Max(texture, Packet.MTU); texture = Math.Max(texture, LLUDPServer.MTU);
asset = Math.Max(asset, Packet.MTU); asset = Math.Max(asset, LLUDPServer.MTU);
state = Math.Max(state, Packet.MTU); state = Math.Max(state, LLUDPServer.MTU);
int total = resend + land + wind + cloud + task + texture + asset + state; int total = resend + land + wind + cloud + task + texture + asset + state;
@ -404,9 +404,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
TokenBucket bucket; TokenBucket bucket;
bool packetSent = false; bool packetSent = false;
//string queueDebugOutput = String.Empty; // Serious debug business
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
{ {
bucket = m_throttleCategories[i]; bucket = m_throttleCategories[i];
//queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business
if (m_nextPackets[i] != null) 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; return packetSent;
} }

View File

@ -89,6 +89,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// </summary> /// </summary>
public class LLUDPServer : OpenSimUDPBase public class LLUDPServer : OpenSimUDPBase
{ {
/// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
public const int MTU = 1400;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>Handlers for incoming packets</summary> /// <summary>Handlers for incoming packets</summary>
@ -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 // 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 // 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 // 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); UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
@ -569,9 +572,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// client.BytesSinceLastACK. Lockless thread safety // client.BytesSinceLastACK. Lockless thread safety
int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
bytesSinceLastACK += buffer.DataLength; bytesSinceLastACK += buffer.DataLength;
if (bytesSinceLastACK > Packet.MTU * 2) if (bytesSinceLastACK > LLUDPServer.MTU * 2)
{ {
bytesSinceLastACK -= Packet.MTU * 2; bytesSinceLastACK -= LLUDPServer.MTU * 2;
SendAcks(udpClient); SendAcks(udpClient);
} }
Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK); Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);