diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs index 22ffcdc8b6..20d2049608 100644 --- a/OpenSim/Framework/PriorityQueue.cs +++ b/OpenSim/Framework/PriorityQueue.cs @@ -52,6 +52,9 @@ namespace OpenSim.Framework /// Number of queuest (priorities) that are processed immediately /// [] m_heaps = new MinHeap[NumberOfQueues]; private Dictionary m_lookupTable; @@ -61,10 +64,8 @@ namespace OpenSim.Framework // each pass. weighted towards the higher priority queues private uint m_nextQueue = 0; private uint m_countFromQueue = 0; - // first queues are imediate, so no counts -// private uint[] m_queueCounts = { 0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1 }; - private uint[] m_queueCounts = {0, 0, 8, 8, 5, 4, 3, 2, 1, 1, 1, 1}; - // this is ava, ava, attach, <10m, 20,40,80,160m,320,640,1280, + + private int m_capacity; + private int m_added; // next request is a counter of the number of updates queued, it provides // a total ordering on the updates coming through the queue and is more @@ -84,17 +85,29 @@ namespace OpenSim.Framework public PriorityQueue(int capacity) { - m_lookupTable = new Dictionary(capacity); + m_capacity = capacity; + capacity /= 4; for (int i = 0; i < m_heaps.Length; ++i) m_heaps[i] = new MinHeap(capacity); + m_lookupTable = new Dictionary(m_capacity); m_nextQueue = NumberOfImmediateQueues; m_countFromQueue = m_queueCounts[m_nextQueue]; + m_added = 0; } #endregion Constructor #region PublicMethods + public void Close() + { + for (int i = 0; i < m_heaps.Length; ++i) + m_heaps[i] = null; + m_heaps = null; + m_lookupTable.Clear(); + m_lookupTable = null; + } + /// /// Return the number of items in the queues /// @@ -116,14 +129,21 @@ namespace OpenSim.Framework public bool Enqueue(uint pqueue, EntityUpdate value) { LookupItem lookup; + IHandle lookupH; + UInt64 entry; uint localid = value.Entity.LocalId; - UInt64 entry = m_nextRequest++; if (m_lookupTable.TryGetValue(localid, out lookup)) { - entry = lookup.Heap[lookup.Handle].EntryOrder; - value.Update(lookup.Heap[lookup.Handle].Value); - lookup.Heap.Remove(lookup.Handle); + lookupH = lookup.Handle; + entry = lookup.Heap[lookupH].EntryOrder; + value.Update(lookup.Heap[lookupH].Value); + lookup.Heap.Remove(lookupH); + } + else + { + entry = m_nextRequest++; + ++m_added; } pqueue = Util.Clamp(pqueue, 0, NumberOfQueues - 1); @@ -134,7 +154,6 @@ namespace OpenSim.Framework return true; } - public void Remove(List ids) { LookupItem lookup; @@ -147,6 +166,11 @@ namespace OpenSim.Framework m_lookupTable.Remove(localid); } } + if(m_lookupTable.Count == 0 && m_added > 8 * m_capacity) + { + m_lookupTable = new Dictionary(m_capacity); + m_added = 0; + } } /// @@ -156,8 +180,9 @@ namespace OpenSim.Framework /// public bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue) { - // If there is anything in imediate queues, return it first no + // If there is anything in immediate queues, return it first no // matter what else. Breaks fairness. But very useful. + for (int iq = 0; iq < NumberOfImmediateQueues; iq++) { if (m_heaps[iq].Count > 0) @@ -177,12 +202,13 @@ namespace OpenSim.Framework // to give lower numbered queues a higher priority and higher percentage // of the bandwidth. + MinHeap curheap = m_heaps[m_nextQueue]; // Check for more items to be pulled from the current queue - if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0) + if (m_countFromQueue > 0 && curheap.Count > 0) { - m_countFromQueue--; + --m_countFromQueue; - MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); + MinHeapItem item = curheap.RemoveMin(); m_lookupTable.Remove(item.Value.Entity.LocalId); timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); value = item.Value; @@ -196,35 +222,40 @@ namespace OpenSim.Framework m_nextQueue++; if(m_nextQueue >= NumberOfQueues) m_nextQueue = NumberOfImmediateQueues; + + curheap = m_heaps[m_nextQueue]; + if (curheap.Count == 0) + continue; m_countFromQueue = m_queueCounts[m_nextQueue]; + --m_countFromQueue; - if (m_heaps[m_nextQueue].Count > 0) - { - m_countFromQueue--; - - MinHeapItem item = m_heaps[m_nextQueue].RemoveMin(); - m_lookupTable.Remove(item.Value.Entity.LocalId); - timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); - value = item.Value; - return true; - } + MinHeapItem item = curheap.RemoveMin(); + m_lookupTable.Remove(item.Value.Entity.LocalId); + timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); + value = item.Value; + return true; } timeinqueue = 0; value = default(EntityUpdate); + if(m_lookupTable.Count == 0 && m_added > 8 * m_capacity) + { + m_lookupTable = new Dictionary(m_capacity); + m_added = 0; + } return false; } public bool TryOrderedDequeue(out EntityUpdate value, out Int32 timeinqueue) { - // If there is anything in imediate queues, return it first no - // matter what else. Breaks fairness. But very useful. - for (int iq = 0; iq < NumberOfQueues; iq++) + MinHeap curheap; + for (int iq = 0; iq < NumberOfQueues; ++iq) { - if (m_heaps[iq].Count > 0) + curheap = m_heaps[iq]; + if (curheap.Count > 0) { - MinHeapItem item = m_heaps[iq].RemoveMin(); + MinHeapItem item = curheap.RemoveMin(); m_lookupTable.Remove(item.Value.Entity.LocalId); timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); value = item.Value; @@ -234,6 +265,11 @@ namespace OpenSim.Framework timeinqueue = 0; value = default(EntityUpdate); + if(m_lookupTable.Count == 0 && m_added > 8 * m_capacity) + { + m_lookupTable = new Dictionary(m_capacity); + m_added = 0; + } return false; } @@ -244,7 +280,7 @@ namespace OpenSim.Framework public void Reprioritize(UpdatePriorityHandler handler) { MinHeapItem item; - foreach (LookupItem lookup in new List(this.m_lookupTable.Values)) + foreach (LookupItem lookup in new List(m_lookupTable.Values)) { if (lookup.Heap.TryGetValue(lookup.Handle, out item)) { @@ -270,7 +306,7 @@ namespace OpenSim.Framework { // m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID); lookup.Heap.Remove(lookup.Handle); - this.m_lookupTable.Remove(localid); + m_lookupTable.Remove(localid); } } } @@ -292,48 +328,55 @@ namespace OpenSim.Framework private struct MinHeapItem : IComparable { private EntityUpdate value; - internal EntityUpdate Value { - get { - return this.value; + internal EntityUpdate Value + { + get + { + return value; } } private uint pqueue; - internal uint PriorityQueue { - get { - return this.pqueue; + internal uint PriorityQueue + { + get + { + return pqueue; } } private Int32 entrytime; - internal Int32 EntryTime { - get { - return this.entrytime; + internal Int32 EntryTime + { + get + { + return entrytime; } } private UInt64 entryorder; internal UInt64 EntryOrder { - get { - return this.entryorder; + get + { + return entryorder; } } - internal MinHeapItem(uint pqueue, MinHeapItem other) + internal MinHeapItem(uint _pqueue, MinHeapItem other) { - this.entrytime = other.entrytime; - this.entryorder = other.entryorder; - this.value = other.value; - this.pqueue = pqueue; + entrytime = other.entrytime; + entryorder = other.entryorder; + value = other.value; + pqueue = _pqueue; } - internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value) + internal MinHeapItem(uint _pqueue, UInt64 _entryorder, EntityUpdate _value) { - this.entrytime = Util.EnvironmentTickCount(); - this.entryorder = entryorder; - this.value = value; - this.pqueue = pqueue; + entrytime = Util.EnvironmentTickCount(); + entryorder = _entryorder; + value = _value; + pqueue = _pqueue; } public override string ToString() diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 516c1e51cc..bbaa0e27ed 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -627,10 +627,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP ImageManager.Close(); ImageManager = null; -// m_entityUpdates.Close(); -// m_entityProps.Close(); - m_entityUpdates = new PriorityQueue(1); - m_entityProps = new PriorityQueue(1); + m_entityUpdates.Close(); + m_entityProps.Close(); m_killRecord.Clear(); GroupsInView.Clear(); @@ -2683,11 +2681,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks) { ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect); - packet.Header.Reliable = false; - packet.Header.Zerocoded = true; - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; +// packet.AgentData.AgentID = AgentId; +// packet.AgentData.SessionID = SessionId; packet.Effect = effectBlocks; diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 53ca849fb1..cc4df17222 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -33,27 +33,12 @@ using OpenSim.Framework; using OpenMetaverse; using OpenSim.Region.PhysicsModules.SharedBase; -/* - * Steps to add a new prioritization policy: - * - * - Add a new value to the UpdatePrioritizationSchemes enum. - * - Specify this new value in the [InterestManagement] section of your - * OpenSim.ini. The name in the config file must match the enum value name - * (although it is not case sensitive). - * - Write a new GetPriorityBy*() method in this class. - * - Add a new entry to the switch statement in GetUpdatePriority() that calls - * your method. - */ - namespace OpenSim.Region.Framework.Scenes { public enum UpdatePrioritizationSchemes { - Time = 0, - Distance = 1, - SimpleAngularDistance = 2, - FrontBack = 3, - BestAvatarResponsiveness = 4, + SimpleAngularDistance = 0, + BestAvatarResponsiveness = 1, } public class Prioritizer @@ -68,14 +53,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Returns the priority queue into which the update should be placed. Updates within a - /// queue will be processed in arrival order. There are currently 12 priority queues - /// implemented in PriorityQueue class in LLClientView. Queue 0 is generally retained - /// for avatar updates. The fair queuing discipline for processing the priority queues - /// assumes that the number of entities in each priority queues increases exponentially. - /// So for example... if queue 1 contains all updates within 10m of the avatar or camera - /// then queue 2 at 20m is about 3X bigger in space & about 3X bigger in total number - /// of updates. + /// Returns the priority queue into which the update should be placed. /// public uint GetUpdatePriority(IClientAPI client, ISceneEntity entity) { @@ -94,22 +72,8 @@ namespace OpenSim.Region.Framework.Scenes switch (m_scene.UpdatePrioritizationScheme) { -/* - case UpdatePrioritizationSchemes.Time: - priority = GetPriorityByTime(client, entity); - break; - case UpdatePrioritizationSchemes.Distance: - priority = GetPriorityByDistance(client, entity); - break; case UpdatePrioritizationSchemes.SimpleAngularDistance: - priority = GetPriorityByDistance(client, entity); // TODO: Reimplement SimpleAngularDistance - break; - case UpdatePrioritizationSchemes.FrontBack: - priority = GetPriorityByFrontBack(client, entity); - break; -*/ - case UpdatePrioritizationSchemes.SimpleAngularDistance: - priority = GetPriorityByAngularDistance(client, entity); // TODO: Reimplement SimpleAngularDistance + priority = GetPriorityByAngularDistance(client, entity); break; case UpdatePrioritizationSchemes.BestAvatarResponsiveness: default: @@ -120,45 +84,6 @@ namespace OpenSim.Region.Framework.Scenes return priority; } - private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity) - { - // And anything attached to this avatar gets top priority as well - if (entity is SceneObjectPart) - { - SceneObjectPart sop = (SceneObjectPart)entity; - if (sop.ParentGroup.IsAttachment && client.AgentId == sop.ParentGroup.AttachedAvatar) - return 1; - } - - return PriorityQueue.NumberOfImmediateQueues; // first queue past the immediate queues - } - - private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity) - { - // And anything attached to this avatar gets top priority as well - if (entity is SceneObjectPart) - { - SceneObjectPart sop = (SceneObjectPart)entity; - if (sop.ParentGroup.IsAttachment && client.AgentId == sop.ParentGroup.AttachedAvatar) - return 1; - } - - return ComputeDistancePriority(client,entity,false); - } - - private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) - { - // And anything attached to this avatar gets top priority as well - if (entity is SceneObjectPart) - { - SceneObjectPart sop = (SceneObjectPart)entity; - if (sop.ParentGroup.IsAttachment && client.AgentId == sop.ParentGroup.AttachedAvatar) - return 1; - } - - return ComputeDistancePriority(client,entity,true); - } - private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) { uint pqueue = 2; // keep compiler happy @@ -176,7 +101,6 @@ namespace OpenSim.Region.Framework.Scenes // Attachments are high priority, if (sog.IsAttachment) return 2; - if(presence.ParentPart != null) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a21b4f7bcd..2e14a20502 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1115,7 +1115,7 @@ namespace OpenSim.Region.Framework.Scenes catch (Exception) { m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); - UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; + UpdatePrioritizationScheme = UpdatePrioritizationSchemes.BestAvatarResponsiveness; } IsReprioritizationEnabled @@ -1196,7 +1196,7 @@ namespace OpenSim.Region.Framework.Scenes UseBackup = true; IsReprioritizationEnabled = true; - UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; + UpdatePrioritizationScheme = UpdatePrioritizationSchemes.BestAvatarResponsiveness; ReprioritizationInterval = 5000; ReprioritizationDistance = m_minReprioritizationDistance; @@ -1762,7 +1762,7 @@ namespace OpenSim.Region.Framework.Scenes } m_sceneGridService.InformNeighborsThatRegionisUp( - RequestModuleInterface(), RegionInfo); + RequestModuleInterface(), RegionInfo); // Region ready should always be set Ready = true;