Experimental change to use an immutable array for iterating ScenePresences, avoiding locking and copying the list each time it is accessed

This commit is contained in:
John Hurliman
2009-10-23 01:02:36 -07:00
parent 96d53f11e5
commit 588361e2a2
13 changed files with 312 additions and 288 deletions

View File

@@ -66,7 +66,9 @@ namespace OpenSim.Region.Framework.Scenes
#region Fields
protected internal Dictionary<UUID, ScenePresence> ScenePresences = new Dictionary<UUID, ScenePresence>();
protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>();
protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0];
// SceneObjects is not currently populated or used.
//public Dictionary<UUID, SceneObjectGroup> SceneObjects;
protected internal EntityManager Entities = new EntityManager();
@@ -126,10 +128,12 @@ namespace OpenSim.Region.Framework.Scenes
protected internal void Close()
{
lock (ScenePresences)
lock (m_scenePresences)
{
ScenePresences.Clear();
m_scenePresences.Clear();
m_scenePresenceArray = new ScenePresence[0];
}
lock (m_dictionary_lock)
{
SceneObjectGroupsByFullID.Clear();
@@ -157,11 +161,9 @@ namespace OpenSim.Region.Framework.Scenes
protected internal void UpdatePresences()
{
List<ScenePresence> updateScenePresences = GetScenePresences();
foreach (ScenePresence pres in updateScenePresences)
{
pres.Update();
}
ScenePresence[] updateScenePresences = GetScenePresences();
for (int i = 0; i < updateScenePresences.Length; i++)
updateScenePresences[i].Update();
}
protected internal float UpdatePhysics(double elapsed)
@@ -190,15 +192,9 @@ namespace OpenSim.Region.Framework.Scenes
protected internal void UpdateScenePresenceMovement()
{
List<ScenePresence> moveEntities = GetScenePresences();
foreach (EntityBase entity in moveEntities)
{
//cfk. This throws occaisional exceptions on a heavily used region
//and I added this null check to try to preclude the exception.
if (entity != null)
entity.UpdateMovement();
}
ScenePresence[] moveEntities = GetScenePresences();
for (int i = 0; i < moveEntities.Length; i++)
moveEntities[i].UpdateMovement();
}
#endregion
@@ -645,9 +641,34 @@ namespace OpenSim.Region.Framework.Scenes
Entities[presence.UUID] = presence;
lock (ScenePresences)
lock (m_scenePresences)
{
ScenePresences[presence.UUID] = presence;
if (!m_scenePresences.ContainsKey(presence.UUID))
{
m_scenePresences.Add(presence.UUID, presence);
// Create a new array of ScenePresence references
int oldLength = m_scenePresenceArray.Length;
ScenePresence[] newArray = new ScenePresence[oldLength + 1];
Array.Copy(m_scenePresenceArray, newArray, oldLength);
newArray[oldLength] = presence;
m_scenePresenceArray = newArray;
}
else
{
m_scenePresences[presence.UUID] = presence;
// Do a linear search through the array of ScenePresence references
// and update the modified entry
for (int i = 0; i < m_scenePresenceArray.Length; i++)
{
if (m_scenePresenceArray[i].UUID == presence.UUID)
{
m_scenePresenceArray[i] = presence;
break;
}
}
}
}
}
@@ -663,16 +684,30 @@ namespace OpenSim.Region.Framework.Scenes
agentID);
}
lock (ScenePresences)
lock (m_scenePresences)
{
if (!ScenePresences.Remove(agentID))
if (m_scenePresences.Remove(agentID))
{
// Copy all of the elements from the previous array
// into the new array except the removed element
int oldLength = m_scenePresenceArray.Length;
ScenePresence[] newArray = new ScenePresence[oldLength - 1];
int j = 0;
for (int i = 0; i < m_scenePresenceArray.Length; i++)
{
ScenePresence presence = m_scenePresenceArray[i];
if (presence.UUID != agentID)
{
newArray[j] = presence;
++j;
}
}
m_scenePresenceArray = newArray;
}
else
{
m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
}
// else
// {
// m_log.InfoFormat("[SCENE] Removed scene presence {0} from scene presences list", agentID);
// }
}
}
@@ -704,20 +739,21 @@ namespace OpenSim.Region.Framework.Scenes
public void RecalculateStats()
{
List<ScenePresence> SPList = GetScenePresences();
ScenePresence[] presences = GetScenePresences();
int rootcount = 0;
int childcount = 0;
foreach (ScenePresence user in SPList)
for (int i = 0; i < presences.Length; i++)
{
ScenePresence user = presences[i];
if (user.IsChildAgent)
childcount++;
++childcount;
else
rootcount++;
++rootcount;
}
m_numRootAgents = rootcount;
m_numChildAgents = childcount;
}
public int GetChildAgentCount()
@@ -767,12 +803,9 @@ namespace OpenSim.Region.Framework.Scenes
/// locking is required to iterate over it.
/// </summary>
/// <returns></returns>
protected internal List<ScenePresence> GetScenePresences()
protected internal ScenePresence[] GetScenePresences()
{
lock (ScenePresences)
{
return new List<ScenePresence>(ScenePresences.Values);
}
return m_scenePresenceArray;
}
protected internal List<ScenePresence> GetAvatars()
@@ -817,14 +850,13 @@ namespace OpenSim.Region.Framework.Scenes
// No locking of scene presences here since we're passing back a list...
List<ScenePresence> result = new List<ScenePresence>();
List<ScenePresence> ScenePresencesList = GetScenePresences();
ScenePresence[] scenePresences = GetScenePresences();
foreach (ScenePresence avatar in ScenePresencesList)
for (int i = 0; i < scenePresences.Length; i++)
{
ScenePresence avatar = scenePresences[i];
if (filter(avatar))
{
result.Add(avatar);
}
}
return result;
@@ -839,9 +871,9 @@ namespace OpenSim.Region.Framework.Scenes
{
ScenePresence sp;
lock (ScenePresences)
lock (m_scenePresences)
{
ScenePresences.TryGetValue(agentID, out sp);
m_scenePresences.TryGetValue(agentID, out sp);
}
return sp;
@@ -1000,48 +1032,24 @@ namespace OpenSim.Region.Framework.Scenes
protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
{
ScenePresence presence;
lock (ScenePresences)
{
if (ScenePresences.TryGetValue(avatarId, out presence))
{
avatar = presence;
return true;
//if (!presence.IsChildAgent)
//{
// avatar = presence;
// return true;
//}
//else
//{
// m_log.WarnFormat(
// "[INNER SCENE]: Requested avatar {0} could not be found in scene {1} since it is only registered as a child agent!",
// avatarId, m_parentScene.RegionInfo.RegionName);
//}
}
}
avatar = null;
return false;
lock (m_scenePresences)
return m_scenePresences.TryGetValue(avatarId, out avatar);
}
protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
{
lock (ScenePresences)
{
foreach (ScenePresence presence in ScenePresences.Values)
{
if (!presence.IsChildAgent)
{
string name = presence.ControllingClient.Name;
ScenePresence[] presences = GetScenePresences();
if (String.Compare(avatarName, name, true) == 0)
{
avatar = presence;
return true;
}
for (int i = 0; i < presences.Length; i++)
{
ScenePresence presence = presences[i];
if (!presence.IsChildAgent)
{
if (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0)
{
avatar = presence;
return true;
}
}
}