From ac944def3fbea9cbad58780e3996e4c586237ab5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 2 May 2009 00:14:04 +0000 Subject: [PATCH] Fix the issue that stopped the packet pool from working. Add a mechanism to recycley data blocs within a packet. Recycle the ObjectUpdate* data blocks. Speeds up loading even more. This may mean that the packet pool is now viable. --- OpenSim/Framework/PacketPool.cs | 66 +++++++++++++++++++ .../ClientStack/LindenUDP/LLClientView.cs | 13 ++-- .../ClientStack/LindenUDP/LLPacketHandler.cs | 6 +- .../Avatar/InstantMessage/MuteListModule.cs | 2 +- 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/OpenSim/Framework/PacketPool.cs b/OpenSim/Framework/PacketPool.cs index a4f7d96c61..4d9591e2bd 100644 --- a/OpenSim/Framework/PacketPool.cs +++ b/OpenSim/Framework/PacketPool.cs @@ -34,6 +34,7 @@ using log4net; namespace OpenSim.Framework { + public sealed class PacketPool { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -44,6 +45,9 @@ namespace OpenSim.Framework private readonly Dictionary> pool = new Dictionary>(); + private static Dictionary> DataBlocks = + new Dictionary>(); + static PacketPool() { } @@ -136,6 +140,28 @@ namespace OpenSim.Framework /// public void ReturnPacket(Packet packet) { + switch (packet.Type) + { + case PacketType.ObjectUpdate: + ObjectUpdatePacket oup = (ObjectUpdatePacket)packet; + + foreach (ObjectUpdatePacket.ObjectDataBlock oupod in + oup.ObjectData) + ReturnDataBlock(oupod); + oup.ObjectData = null; + break; + + case PacketType.ImprovedTerseObjectUpdate: + ImprovedTerseObjectUpdatePacket itoup = + (ImprovedTerseObjectUpdatePacket)packet; + + foreach (ImprovedTerseObjectUpdatePacket.ObjectDataBlock + itoupod in itoup.ObjectData) + ReturnDataBlock(itoupod); + itoup.ObjectData = null; + break; + } + if (!packetPoolEnabled) return; @@ -163,5 +189,45 @@ namespace OpenSim.Framework return; } } + + public static T GetDataBlock() where T: new() + { + lock(DataBlocks) + { + if (DataBlocks.ContainsKey(typeof(T)) && DataBlocks[typeof(T)].Count > 0) + { + T block = (T)DataBlocks[typeof(T)][0]; + DataBlocks[typeof(T)].RemoveAt(0); + if (block == null) + return new T(); + return block; + } + else + { + return new T(); + } + } + } + + public static void ReturnDataBlock(T block) where T: new() + { + if (block == null) + return; + + lock (DataBlocks) + { + if (!DataBlocks.ContainsKey(typeof(T))) + { + List l = new List(); + l.Add(block); + DataBlocks.Add(typeof(T), l); + } + else + { + if (DataBlocks[typeof(T)].Count < 500) + DataBlocks[typeof(T)].Add(block); + } + } + } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 05ebcacc41..4acc6bead4 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -2893,10 +2893,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) rotation = Quaternion.Identity; - ObjectUpdatePacket.ObjectDataBlock objectData = - new ObjectUpdatePacket.ObjectDataBlock(); - - objectData = CreatePrimUpdateBlock(primShape, flags); + ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); objectData.ID = localID; objectData.FullID = objectID; @@ -3655,7 +3652,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { byte[] bytes = new byte[60]; int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; @@ -3750,7 +3747,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] bytes = new byte[60]; int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); dat.TextureEntry = new byte[0]; bytes[i++] = (byte)(ID % 256); bytes[i++] = (byte)((ID >> 8) % 256); @@ -3837,7 +3834,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) { - ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock(); + ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock(); SetDefaultPrimPacketValues(objupdate); objupdate.UpdateFlags = flags; SetPrimPacketShapeData(objupdate, primShape); @@ -3908,7 +3905,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) { - ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock(); + ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock(); // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); SetDefaultAvatarPacketValues(ref objdata); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs index 58777ab67d..2191ca7f0f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs @@ -586,7 +586,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; m_NeedAck.Remove(id); - PacketPool.Instance.ReturnPacket(data.Packet); + // We can't return this packet, it will just have to be GC'd + // Reason for that is that the packet may still be in the + // send queue, and if it gets reused things get messy! + // + // PacketPool.Instance.ReturnPacket(data.Packet); m_UnackedBytes -= data.Length; } } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs index d3e5b45a3f..3b1bad069b 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs @@ -129,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList private void OnMuteListRequest(IClientAPI client, uint crc) { - m_log.DebugFormat("[MUTE LIST] Got mute list requestg for crc {0}", crc); + m_log.DebugFormat("[MUTE LIST] Got mute list request for crc {0}", crc); string filename = "mutes"+client.AgentId.ToString(); IXfer xfer = client.Scene.RequestModuleInterface();