Reuse the same AgentUpdateArgs object for each AgentUpdate UDP packet (of which there are 10 a second) rather than constructing a new one every time.

We can do this because AgentUpdate packets are handled synchronously.
0.7.4-extended
Justin Clark-Casey (justincc) 2012-10-17 23:54:05 +01:00
parent 73c2db9e8f
commit 8726748e22
1 changed files with 68 additions and 41 deletions

View File

@ -91,8 +91,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public event ObjectDeselect OnObjectDetach; public event ObjectDeselect OnObjectDetach;
public event ObjectDrop OnObjectDrop; public event ObjectDrop OnObjectDrop;
public event Action<IClientAPI, bool> OnCompleteMovementToRegion; public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
/// <summary>
/// Called when an AgentUpdate message is received and before OnAgentUpdate.
/// </summary>
/// <remarks>
/// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates.
/// </remarks>
public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnPreAgentUpdate;
/// <summary>
/// Called when an AgentUpdate message is received and after OnPreAgentUpdate.
/// </summary>
/// <remarks>
/// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates.
/// </remarks>
public event UpdateAgent OnAgentUpdate; public event UpdateAgent OnAgentUpdate;
public event AgentRequestSit OnAgentRequestSit; public event AgentRequestSit OnAgentRequestSit;
public event AgentSit OnAgentSit; public event AgentSit OnAgentSit;
public event AvatarPickerRequest OnAvatarPickerRequest; public event AvatarPickerRequest OnAvatarPickerRequest;
@ -346,7 +361,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_moneyBalance; private int m_moneyBalance;
private int m_animationSequenceNumber = 1; private int m_animationSequenceNumber = 1;
private bool m_SendLogoutPacketWhenClosing = true; private bool m_SendLogoutPacketWhenClosing = true;
private AgentUpdateArgs lastarg;
/// <summary>
/// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
/// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
/// is doing absolutely nothing.
/// </summary>
/// <remarks>
/// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
/// cannot retain a reference to it outside of that method.
/// </remarks>
private AgentUpdateArgs m_lastAgentUpdateArgs;
protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@ -5197,7 +5222,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected virtual void RegisterLocalPacketHandlers() protected virtual void RegisterLocalPacketHandlers()
{ {
AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
// If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
// for each AgentUpdate packet.
AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
@ -5428,73 +5457,71 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
if (OnAgentUpdate != null) if (OnAgentUpdate != null)
{ {
bool update = false; AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
AgentUpdatePacket agenUpdate = (AgentUpdatePacket)packet;
#region Packet Session and User Check #region Packet Session and User Check
if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId)
{ {
PacketPool.Instance.ReturnPacket(packet); PacketPool.Instance.ReturnPacket(packet);
return false; return false;
} }
#endregion #endregion
AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; bool update = false;
AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
// We can only check when we have something to check if (m_lastAgentUpdateArgs != null)
// against.
if (lastarg != null)
{ {
// These should be ordered from most-likely to
// least likely to change. I've made an initial
// guess at that.
update = update =
( (
(x.BodyRotation != lastarg.BodyRotation) || (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) ||
(x.CameraAtAxis != lastarg.CameraAtAxis) || (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) ||
(x.CameraCenter != lastarg.CameraCenter) || (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
(x.CameraLeftAxis != lastarg.CameraLeftAxis) || (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
(x.CameraUpAxis != lastarg.CameraUpAxis) || (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
(x.ControlFlags != lastarg.ControlFlags) || (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
(x.Far != lastarg.Far) || (x.Far != m_lastAgentUpdateArgs.Far) ||
(x.Flags != lastarg.Flags) || (x.Flags != m_lastAgentUpdateArgs.Flags) ||
(x.State != lastarg.State) || (x.State != m_lastAgentUpdateArgs.State) ||
(x.HeadRotation != lastarg.HeadRotation) || (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
(x.SessionID != lastarg.SessionID) || (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
(x.AgentID != lastarg.AgentID) (x.AgentID != m_lastAgentUpdateArgs.AgentID)
); );
} }
else else
{ {
m_lastAgentUpdateArgs = new AgentUpdateArgs();
update = true; update = true;
} }
// These should be ordered from most-likely to
// least likely to change. I've made an initial
// guess at that.
if (update) if (update)
{ {
// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
AgentUpdateArgs arg = new AgentUpdateArgs(); m_lastAgentUpdateArgs.AgentID = x.AgentID;
arg.AgentID = x.AgentID; m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation;
arg.BodyRotation = x.BodyRotation; m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
arg.CameraAtAxis = x.CameraAtAxis; m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter;
arg.CameraCenter = x.CameraCenter; m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
arg.CameraLeftAxis = x.CameraLeftAxis; m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
arg.CameraUpAxis = x.CameraUpAxis; m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags;
arg.ControlFlags = x.ControlFlags; m_lastAgentUpdateArgs.Far = x.Far;
arg.Far = x.Far; m_lastAgentUpdateArgs.Flags = x.Flags;
arg.Flags = x.Flags; m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
arg.HeadRotation = x.HeadRotation; m_lastAgentUpdateArgs.SessionID = x.SessionID;
arg.SessionID = x.SessionID; m_lastAgentUpdateArgs.State = x.State;
arg.State = x.State;
UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerAgentUpdate = OnAgentUpdate;
UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
lastarg = arg; // save this set of arguments for nexttime
if (handlerPreAgentUpdate != null) if (handlerPreAgentUpdate != null)
OnPreAgentUpdate(this, arg); OnPreAgentUpdate(this, m_lastAgentUpdateArgs);
if (handlerAgentUpdate != null) if (handlerAgentUpdate != null)
OnAgentUpdate(this, arg); OnAgentUpdate(this, m_lastAgentUpdateArgs);
handlerAgentUpdate = null; handlerAgentUpdate = null;
handlerPreAgentUpdate = null; handlerPreAgentUpdate = null;