* Removed the throttle speed optimizations to see if it brings stability back
* Changed the outgoing packet handler to use a real function instead of a closure and to track time on a per-client basis instead of a global basisprioritization
parent
d1ab11dc2a
commit
d38f33736c
|
@ -101,6 +101,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
public bool IsPaused = true;
|
||||
/// <summary>Environment.TickCount when the last packet was received for this client</summary>
|
||||
public int TickLastPacketReceived;
|
||||
/// <summary>Environment.TickCount of the last time the outgoing packet handler executed for this client</summary>
|
||||
public int TickLastOutgoingPacketHandler;
|
||||
|
||||
/// <summary>Timer granularity. This is set to the measured resolution of Environment.TickCount</summary>
|
||||
public readonly float G;
|
||||
|
@ -320,27 +322,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
bucket.MaxBurst = total;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
|
||||
bucket.DripRate = bucket.MaxBurst = resend;
|
||||
bucket.DripRate = resend;
|
||||
bucket.MaxBurst = resend;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
|
||||
bucket.DripRate = bucket.MaxBurst = land;
|
||||
bucket.DripRate = land;
|
||||
bucket.MaxBurst = land;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
|
||||
bucket.DripRate = bucket.MaxBurst = wind;
|
||||
bucket.DripRate = wind;
|
||||
bucket.MaxBurst = wind;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
|
||||
bucket.DripRate = bucket.MaxBurst = cloud;
|
||||
bucket.DripRate = cloud;
|
||||
bucket.MaxBurst = cloud;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
|
||||
bucket.DripRate = bucket.MaxBurst = asset;
|
||||
bucket.DripRate = asset;
|
||||
bucket.MaxBurst = asset;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
|
||||
bucket.DripRate = task + state + texture;
|
||||
bucket.MaxBurst = task + state + texture;
|
||||
bucket.DripRate = task + state;
|
||||
bucket.MaxBurst = task + state;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
|
||||
bucket.DripRate = state + texture;
|
||||
bucket.MaxBurst = state + texture;
|
||||
bucket.DripRate = state;
|
||||
bucket.MaxBurst = state;
|
||||
|
||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
|
||||
bucket.DripRate = texture;
|
||||
|
|
|
@ -118,6 +118,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
private int m_recvBufferSize;
|
||||
/// <summary>Flag to process packets asynchronously or synchronously</summary>
|
||||
private bool m_asyncPacketHandling;
|
||||
/// <summary>Track whether or not a packet was sent in the
|
||||
/// OutgoingPacketHandler loop so we know when to sleep</summary>
|
||||
private bool m_packetSentLastLoop;
|
||||
|
||||
/// <summary>The measured resolution of Environment.TickCount</summary>
|
||||
public float TickCountResolution { get { return m_tickCountResolution; } }
|
||||
|
@ -745,10 +748,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
while (base.IsRunning)
|
||||
{
|
||||
IncomingPacket incomingPacket = null;
|
||||
|
||||
try
|
||||
{
|
||||
IncomingPacket incomingPacket = null;
|
||||
|
||||
if (packetInbox.Dequeue(100, ref incomingPacket))
|
||||
Util.FireAndForget(ProcessInPacket, incomingPacket);
|
||||
}
|
||||
|
@ -769,76 +772,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// on to en-US to avoid number parsing issues
|
||||
Culture.SetCurrentCulture();
|
||||
|
||||
int now = Environment.TickCount;
|
||||
int elapsedMS = 0;
|
||||
int elapsed100MS = 0;
|
||||
int elapsed500MS = 0;
|
||||
|
||||
while (base.IsRunning)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool resendUnacked = false;
|
||||
bool sendAcks = false;
|
||||
bool sendPings = false;
|
||||
bool packetSent = false;
|
||||
m_packetSentLastLoop = false;
|
||||
|
||||
elapsedMS += Environment.TickCount - now;
|
||||
m_scene.ClientManager.ForEachSync(ClientOutgoingPacketHandler);
|
||||
|
||||
// Check for pending outgoing resends every 100ms
|
||||
if (elapsedMS >= 100)
|
||||
{
|
||||
resendUnacked = true;
|
||||
elapsedMS -= 100;
|
||||
++elapsed100MS;
|
||||
}
|
||||
// Check for pending outgoing ACKs every 500ms
|
||||
if (elapsed100MS >= 5)
|
||||
{
|
||||
sendAcks = true;
|
||||
elapsed100MS = 0;
|
||||
++elapsed500MS;
|
||||
}
|
||||
// Send pings to clients every 5000ms
|
||||
if (elapsed500MS >= 10)
|
||||
{
|
||||
sendPings = true;
|
||||
elapsed500MS = 0;
|
||||
}
|
||||
|
||||
m_scene.ClientManager.ForEachSync(
|
||||
delegate(IClientAPI client)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (client is LLClientView)
|
||||
{
|
||||
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
|
||||
|
||||
if (udpClient.IsConnected)
|
||||
{
|
||||
if (udpClient.DequeueOutgoing())
|
||||
packetSent = true;
|
||||
if (resendUnacked)
|
||||
ResendUnacked(udpClient);
|
||||
if (sendAcks)
|
||||
{
|
||||
SendAcks(udpClient);
|
||||
udpClient.SendPacketStats();
|
||||
}
|
||||
if (sendPings)
|
||||
SendPing(udpClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + " threw an exception: " + ex.Message, ex);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!packetSent)
|
||||
// If no packets at all were sent, sleep to avoid chewing up CPU cycles
|
||||
// when there is nothing to do
|
||||
if (!m_packetSentLastLoop)
|
||||
Thread.Sleep(20);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -848,6 +792,52 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
private void ClientOutgoingPacketHandler(IClientAPI client)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (client is LLClientView)
|
||||
{
|
||||
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
|
||||
|
||||
int thisTick = Environment.TickCount & Int32.MaxValue;
|
||||
int elapsedMS = thisTick - udpClient.TickLastOutgoingPacketHandler;
|
||||
|
||||
if (udpClient.IsConnected)
|
||||
{
|
||||
// Check for pending outgoing resends every 100ms
|
||||
if (elapsedMS >= 100)
|
||||
{
|
||||
ResendUnacked(udpClient);
|
||||
|
||||
// Check for pending outgoing ACKs every 500ms
|
||||
if (elapsedMS >= 500)
|
||||
{
|
||||
SendAcks(udpClient);
|
||||
|
||||
// Send pings to clients every 5000ms
|
||||
if (elapsedMS >= 5000)
|
||||
{
|
||||
SendPing(udpClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dequeue any outgoing packets that are within the throttle limits
|
||||
if (udpClient.DequeueOutgoing())
|
||||
m_packetSentLastLoop = true;
|
||||
}
|
||||
|
||||
udpClient.TickLastOutgoingPacketHandler = thisTick;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
|
||||
" threw an exception: " + ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessInPacket(object state)
|
||||
{
|
||||
IncomingPacket incomingPacket = (IncomingPacket)state;
|
||||
|
|
Loading…
Reference in New Issue