Do some simple queue empty checks in the main outgoing udp loop instead of always performing these on a separate fired thread.
This appears to improve cpu usage since launching a new thread is more expensive than performing a small amount of inline logic. However, needs testing at scale.cpu-performance
parent
553d9cc5d2
commit
8c6761c152
|
@ -485,6 +485,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
m_udpServer = udpServer;
|
||||
m_udpClient = udpClient;
|
||||
m_udpClient.OnQueueEmpty += HandleQueueEmpty;
|
||||
m_udpClient.HasUpdates += HandleHasUpdates;
|
||||
m_udpClient.OnPacketStats += PopulateStats;
|
||||
|
||||
m_prioritizer = new Prioritizer(m_scene);
|
||||
|
@ -4133,8 +4134,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
|
||||
{
|
||||
// if (!m_udpServer.IsRunningOutbound)
|
||||
// return;
|
||||
|
||||
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
|
||||
{
|
||||
// if (!m_udpServer.IsRunningOutbound)
|
||||
// return;
|
||||
|
||||
if (m_maxUpdates == 0 || m_LastQueueFill == 0)
|
||||
{
|
||||
m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
|
||||
|
@ -4160,6 +4167,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
|
||||
}
|
||||
|
||||
internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories)
|
||||
{
|
||||
bool hasUpdates = false;
|
||||
|
||||
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
|
||||
{
|
||||
if (m_entityUpdates.Count > 0)
|
||||
hasUpdates = true;
|
||||
else if (m_entityProps.Count > 0)
|
||||
hasUpdates = true;
|
||||
}
|
||||
|
||||
if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
|
||||
{
|
||||
if (ImageManager.HasUpdates())
|
||||
hasUpdates = true;
|
||||
}
|
||||
|
||||
return hasUpdates;
|
||||
}
|
||||
|
||||
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
|
||||
{
|
||||
AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
|
||||
|
|
|
@ -206,6 +206,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
public bool HasUpdates()
|
||||
{
|
||||
J2KImage image = GetHighestPriorityImage();
|
||||
|
||||
return image != null && image.IsDecoded;
|
||||
}
|
||||
|
||||
public bool ProcessImageQueue(int packetsToSend)
|
||||
{
|
||||
int packetsSent = 0;
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Net;
|
|||
using System.Threading;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Monitoring;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
|
@ -81,6 +82,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// hooked to put more data on the empty queue</summary>
|
||||
public event QueueEmpty OnQueueEmpty;
|
||||
|
||||
public event Func<ThrottleOutPacketTypeFlags, bool> HasUpdates;
|
||||
|
||||
/// <summary>AgentID for this client</summary>
|
||||
public readonly UUID AgentID;
|
||||
/// <summary>The remote address of the connected client</summary>
|
||||
|
@ -613,15 +616,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <param name="categories">Throttle categories to fire the callback for</param>
|
||||
private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
|
||||
{
|
||||
if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
|
||||
// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
|
||||
if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
|
||||
{
|
||||
m_isQueueEmptyRunning = true;
|
||||
|
||||
int start = Environment.TickCount & Int32.MaxValue;
|
||||
const int MIN_CALLBACK_MS = 30;
|
||||
|
||||
m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
|
||||
if (m_nextOnQueueEmpty == 0)
|
||||
m_nextOnQueueEmpty = 1;
|
||||
|
||||
// Use a value of 0 to signal that FireQueueEmpty is running
|
||||
m_nextOnQueueEmpty = 0;
|
||||
// Asynchronously run the callback
|
||||
Util.FireAndForget(FireQueueEmpty, categories);
|
||||
// m_nextOnQueueEmpty = 0;
|
||||
|
||||
m_categories = categories;
|
||||
|
||||
if (HasUpdates(m_categories))
|
||||
{
|
||||
// Asynchronously run the callback
|
||||
Util.FireAndForget(FireQueueEmpty, categories);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_isQueueEmptyRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_isQueueEmptyRunning;
|
||||
private ThrottleOutPacketTypeFlags m_categories = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Fires the OnQueueEmpty callback and sets the minimum time that it
|
||||
/// can be called again
|
||||
|
@ -631,22 +657,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// signature</param>
|
||||
private void FireQueueEmpty(object o)
|
||||
{
|
||||
const int MIN_CALLBACK_MS = 30;
|
||||
// int start = Environment.TickCount & Int32.MaxValue;
|
||||
// const int MIN_CALLBACK_MS = 30;
|
||||
|
||||
ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
|
||||
QueueEmpty callback = OnQueueEmpty;
|
||||
|
||||
int start = Environment.TickCount & Int32.MaxValue;
|
||||
// if (m_udpServer.IsRunningOutbound)
|
||||
// {
|
||||
ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
|
||||
QueueEmpty callback = OnQueueEmpty;
|
||||
|
||||
if (callback != null)
|
||||
{
|
||||
try { callback(categories); }
|
||||
catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
|
||||
}
|
||||
if (callback != null)
|
||||
{
|
||||
// if (m_udpServer.IsRunningOutbound)
|
||||
// {
|
||||
try { callback(categories); }
|
||||
catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
|
||||
// }
|
||||
}
|
||||
// }
|
||||
|
||||
m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
|
||||
if (m_nextOnQueueEmpty == 0)
|
||||
m_nextOnQueueEmpty = 1;
|
||||
// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
|
||||
// if (m_nextOnQueueEmpty == 0)
|
||||
// m_nextOnQueueEmpty = 1;
|
||||
|
||||
// }
|
||||
|
||||
m_isQueueEmptyRunning = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1662,8 +1662,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// Action generic every round
|
||||
Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
|
||||
|
||||
// while (true)
|
||||
while (base.IsRunningOutbound)
|
||||
while (true)
|
||||
// while (base.IsRunningOutbound)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -308,8 +308,8 @@ namespace OpenMetaverse
|
|||
|
||||
public void AsyncBeginSend(UDPPacketBuffer buf)
|
||||
{
|
||||
if (IsRunningOutbound)
|
||||
{
|
||||
// if (IsRunningOutbound)
|
||||
// {
|
||||
try
|
||||
{
|
||||
m_udpSocket.BeginSendTo(
|
||||
|
@ -323,7 +323,7 @@ namespace OpenMetaverse
|
|||
}
|
||||
catch (SocketException) { }
|
||||
catch (ObjectDisposedException) { }
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void AsyncEndSend(IAsyncResult result)
|
||||
|
|
Loading…
Reference in New Issue