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_udpServer = udpServer;
|
||||||
m_udpClient = udpClient;
|
m_udpClient = udpClient;
|
||||||
m_udpClient.OnQueueEmpty += HandleQueueEmpty;
|
m_udpClient.OnQueueEmpty += HandleQueueEmpty;
|
||||||
|
m_udpClient.HasUpdates += HandleHasUpdates;
|
||||||
m_udpClient.OnPacketStats += PopulateStats;
|
m_udpClient.OnPacketStats += PopulateStats;
|
||||||
|
|
||||||
m_prioritizer = new Prioritizer(m_scene);
|
m_prioritizer = new Prioritizer(m_scene);
|
||||||
|
@ -4133,8 +4134,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
|
void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
|
||||||
{
|
{
|
||||||
|
// if (!m_udpServer.IsRunningOutbound)
|
||||||
|
// return;
|
||||||
|
|
||||||
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
|
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
|
||||||
{
|
{
|
||||||
|
// if (!m_udpServer.IsRunningOutbound)
|
||||||
|
// return;
|
||||||
|
|
||||||
if (m_maxUpdates == 0 || m_LastQueueFill == 0)
|
if (m_maxUpdates == 0 || m_LastQueueFill == 0)
|
||||||
{
|
{
|
||||||
m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
|
m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
|
||||||
|
@ -4160,6 +4167,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
|
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)
|
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
|
||||||
{
|
{
|
||||||
AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
|
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)
|
public bool ProcessImageQueue(int packetsToSend)
|
||||||
{
|
{
|
||||||
int packetsSent = 0;
|
int packetsSent = 0;
|
||||||
|
|
|
@ -31,6 +31,7 @@ using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using log4net;
|
using log4net;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.Packets;
|
using OpenMetaverse.Packets;
|
||||||
|
|
||||||
|
@ -81,6 +82,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// hooked to put more data on the empty queue</summary>
|
/// hooked to put more data on the empty queue</summary>
|
||||||
public event QueueEmpty OnQueueEmpty;
|
public event QueueEmpty OnQueueEmpty;
|
||||||
|
|
||||||
|
public event Func<ThrottleOutPacketTypeFlags, bool> HasUpdates;
|
||||||
|
|
||||||
/// <summary>AgentID for this client</summary>
|
/// <summary>AgentID for this client</summary>
|
||||||
public readonly UUID AgentID;
|
public readonly UUID AgentID;
|
||||||
/// <summary>The remote address of the connected client</summary>
|
/// <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>
|
/// <param name="categories">Throttle categories to fire the callback for</param>
|
||||||
private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
|
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
|
// Use a value of 0 to signal that FireQueueEmpty is running
|
||||||
m_nextOnQueueEmpty = 0;
|
// m_nextOnQueueEmpty = 0;
|
||||||
// Asynchronously run the callback
|
|
||||||
Util.FireAndForget(FireQueueEmpty, categories);
|
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>
|
/// <summary>
|
||||||
/// Fires the OnQueueEmpty callback and sets the minimum time that it
|
/// Fires the OnQueueEmpty callback and sets the minimum time that it
|
||||||
/// can be called again
|
/// can be called again
|
||||||
|
@ -631,22 +657,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// signature</param>
|
/// signature</param>
|
||||||
private void FireQueueEmpty(object o)
|
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;
|
// if (m_udpServer.IsRunningOutbound)
|
||||||
QueueEmpty callback = OnQueueEmpty;
|
// {
|
||||||
|
ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
|
||||||
int start = Environment.TickCount & Int32.MaxValue;
|
QueueEmpty callback = OnQueueEmpty;
|
||||||
|
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
{
|
{
|
||||||
try { callback(categories); }
|
// if (m_udpServer.IsRunningOutbound)
|
||||||
catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
|
// {
|
||||||
}
|
try { callback(categories); }
|
||||||
|
catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
|
||||||
m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
|
// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
|
||||||
if (m_nextOnQueueEmpty == 0)
|
// if (m_nextOnQueueEmpty == 0)
|
||||||
m_nextOnQueueEmpty = 1;
|
// m_nextOnQueueEmpty = 1;
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
m_isQueueEmptyRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1662,8 +1662,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// Action generic every round
|
// Action generic every round
|
||||||
Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
|
Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
|
||||||
|
|
||||||
// while (true)
|
while (true)
|
||||||
while (base.IsRunningOutbound)
|
// while (base.IsRunningOutbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -308,8 +308,8 @@ namespace OpenMetaverse
|
||||||
|
|
||||||
public void AsyncBeginSend(UDPPacketBuffer buf)
|
public void AsyncBeginSend(UDPPacketBuffer buf)
|
||||||
{
|
{
|
||||||
if (IsRunningOutbound)
|
// if (IsRunningOutbound)
|
||||||
{
|
// {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_udpSocket.BeginSendTo(
|
m_udpSocket.BeginSendTo(
|
||||||
|
@ -323,7 +323,7 @@ namespace OpenMetaverse
|
||||||
}
|
}
|
||||||
catch (SocketException) { }
|
catch (SocketException) { }
|
||||||
catch (ObjectDisposedException) { }
|
catch (ObjectDisposedException) { }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEndSend(IAsyncResult result)
|
void AsyncEndSend(IAsyncResult result)
|
||||||
|
|
Loading…
Reference in New Issue