aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2014-08-28 18:15:33 +0100
committerJustin Clark-Casey (justincc)2014-08-28 18:15:33 +0100
commitf132f642b23d9d0c336354a0bc4bb95c41023c34 (patch)
treea57e83357909161af8e5b735ec93916bff9765c4 /OpenSim/Region
parentDon't allow update timer to invoke another scene update if the previous is st... (diff)
downloadopensim-SC-f132f642b23d9d0c336354a0bc4bb95c41023c34.zip
opensim-SC-f132f642b23d9d0c336354a0bc4bb95c41023c34.tar.gz
opensim-SC-f132f642b23d9d0c336354a0bc4bb95c41023c34.tar.bz2
opensim-SC-f132f642b23d9d0c336354a0bc4bb95c41023c34.tar.xz
On code section that rezzes single objects and attachments, reduce CPU use by reading asset XML a single time with a stream reader rather than multiple times.
Reading large XML documents (e.g. complex attachments) is CPU expensive - this must be done as few times as possible (preferably just once). Reading these documents into XmlDocument is also more resource intensive than using XmlTextReader, as per Microsoft's own publication "Improve .NET Application Performance and Scalability" Optimization of other cases will follow if this change is successful.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs97
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs67
5 files changed, 128 insertions, 71 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index b4771fd..8528c65 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -798,7 +798,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
798 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 798 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
799 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 799 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
800 { 800 {
801 AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); 801 AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString());
802 802
803 if (rezAsset == null) 803 if (rezAsset == null)
804 { 804 {
@@ -829,7 +829,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
829 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 829 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
830 Vector3 pos; 830 Vector3 pos;
831 831
832 bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight); 832 bool single
833 = m_Scene.GetObjectsToRez(
834 rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
833 835
834 if (single) 836 if (single)
835 { 837 {
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
index ad1a0e1..80b9c0a 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -111,6 +111,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
111 InventoryFolderBase objsFolder 111 InventoryFolderBase objsFolder
112 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; 112 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0];
113 item1.Folder = objsFolder.ID; 113 item1.Folder = objsFolder.ID;
114 item1.Flags |= (uint)InventoryItemFlags.ObjectHasMultipleItems;
114 m_scene.AddInventoryItem(item1); 115 m_scene.AddInventoryItem(item1);
115 116
116 SceneObjectGroup so 117 SceneObjectGroup so
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 542d454..cbb4fe7 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Collections; 30using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Threading;
33using System.Timers; 34using System.Timers;
34using System.Xml; 35using System.Xml;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -2192,60 +2193,84 @@ namespace OpenSim.Region.Framework.Scenes
2192 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object. 2193 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2193 /// </remarks> 2194 /// </remarks>
2194 /// <param name="assetData">Asset data</param> 2195 /// <param name="assetData">Asset data</param>
2195 /// <param name="attachment">Whether the item is an attachment</param> 2196 /// <param name="isAttachment">True if the object is an attachment.</param>
2196 /// <param name="objlist">The objects included in the asset</param> 2197 /// <param name="objlist">The objects included in the asset</param>
2197 /// <param name="veclist">Relative positions of the objects</param> 2198 /// <param name="veclist">Relative positions of the objects</param>
2198 /// <param name="bbox">Bounding box of all the objects</param> 2199 /// <param name="bbox">Bounding box of all the objects</param>
2199 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box 2200 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2200 /// to the centre of the root prim (relevant only when returning a single object)</param> 2201 /// to the centre of the root prim (relevant only when returning a single object)</param>
2201 /// <returns>true = returning a single object; false = multiple objects</returns> 2202 /// <returns>
2202 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, 2203 /// true if returning a single object or deserialization fails, false if returning the coalesced
2204 /// list of objects
2205 /// </returns>
2206 public bool GetObjectsToRez(
2207 byte[] assetData, bool isAttachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2203 out Vector3 bbox, out float offsetHeight) 2208 out Vector3 bbox, out float offsetHeight)
2204 { 2209 {
2205 objlist = new List<SceneObjectGroup>(); 2210 objlist = new List<SceneObjectGroup>();
2206 veclist = new List<Vector3>(); 2211 veclist = new List<Vector3>();
2207 2212
2208 XmlDocument doc = new XmlDocument();
2209 string xmlData = Utils.BytesToString(assetData); 2213 string xmlData = Utils.BytesToString(assetData);
2210 doc.LoadXml(xmlData);
2211 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2212 2214
2213 if (e == null || attachment) // Single 2215 try
2214 { 2216 {
2215 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 2217 using (XmlTextReader reader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
2216 objlist.Add(g); 2218 {
2217 veclist.Add(new Vector3(0, 0, 0)); 2219 reader.Read();
2218 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); 2220 bool isSingleObject = reader.Name != "CoalescedObject";
2219 return true; 2221
2222 if (isSingleObject || isAttachment)
2223 {
2224 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(reader);
2225 objlist.Add(g);
2226 veclist.Add(Vector3.Zero);
2227 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2228 return true;
2229 }
2230 else
2231 {
2232 XmlDocument doc = new XmlDocument();
2233 doc.LoadXml(xmlData);
2234 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2235 XmlElement coll = (XmlElement)e;
2236 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2237 float by = Convert.ToSingle(coll.GetAttribute("y"));
2238 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2239 bbox = new Vector3(bx, by, bz);
2240 offsetHeight = 0;
2241
2242 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2243 foreach (XmlNode n in groups)
2244 {
2245 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2246 objlist.Add(g);
2247
2248 XmlElement el = (XmlElement)n;
2249 string rawX = el.GetAttribute("offsetx");
2250 string rawY = el.GetAttribute("offsety");
2251 string rawZ = el.GetAttribute("offsetz");
2252
2253 float x = Convert.ToSingle(rawX);
2254 float y = Convert.ToSingle(rawY);
2255 float z = Convert.ToSingle(rawZ);
2256 veclist.Add(new Vector3(x, y, z));
2257 }
2258
2259 return false;
2260 }
2261 }
2220 } 2262 }
2221 else 2263 catch (Exception e)
2222 { 2264 {
2223 XmlElement coll = (XmlElement)e; 2265 m_log.Error(
2224 float bx = Convert.ToSingle(coll.GetAttribute("x")); 2266 "[AGENT INVENTORY]: Deserialization of xml failed when looking for CoalescedObject tag. Exception ",
2225 float by = Convert.ToSingle(coll.GetAttribute("y")); 2267 e);
2226 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2227 bbox = new Vector3(bx, by, bz);
2228 offsetHeight = 0;
2229 2268
2230 XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); 2269 bbox = Vector3.Zero;
2231 foreach (XmlNode n in groups) 2270 offsetHeight = 0;
2232 {
2233 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2234 objlist.Add(g);
2235
2236 XmlElement el = (XmlElement)n;
2237 string rawX = el.GetAttribute("offsetx");
2238 string rawY = el.GetAttribute("offsety");
2239 string rawZ = el.GetAttribute("offsetz");
2240
2241 float x = Convert.ToSingle(rawX);
2242 float y = Convert.ToSingle(rawY);
2243 float z = Convert.ToSingle(rawZ);
2244 veclist.Add(new Vector3(x, y, z));
2245 }
2246 } 2271 }
2247 2272
2248 return false; 2273 return true;
2249 } 2274 }
2250 2275
2251 /// <summary> 2276 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 69491b7..c95d207 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -902,6 +902,34 @@ namespace OpenSim.Region.Framework.Scenes
902 } 902 }
903 } 903 }
904 904
905 public void LoadScriptState(XmlTextReader reader)
906 {
907// m_log.DebugFormat("[SCENE OBJECT GROUP]: Looking for script state for {0} in {1}", Name);
908
909 while (reader.ReadToFollowing("SavedScriptState"))
910 {
911// m_log.DebugFormat("[SCENE OBJECT GROUP]: Loading script state for {0}", Name);
912
913 if (m_savedScriptState == null)
914 m_savedScriptState = new Dictionary<UUID, string>();
915
916 string uuid = reader.GetAttribute("UUID");
917
918 if (uuid != null)
919 {
920// m_log.DebugFormat("[SCENE OBJECT GROUP]: Found state for item ID {0} in object {1}", uuid, Name);
921
922 UUID itemid = new UUID(uuid);
923 if (itemid != UUID.Zero)
924 m_savedScriptState[itemid] = reader.ReadInnerXml();
925 }
926 else
927 {
928 m_log.WarnFormat("[SCENE OBJECT GROUP]: SavedScriptState element had no UUID in object {0}", Name);
929 }
930 }
931 }
932
905 /// <summary> 933 /// <summary>
906 /// Hooks this object up to the backup event so that it is persisted to the database when the update thread executes. 934 /// Hooks this object up to the backup event so that it is persisted to the database when the update thread executes.
907 /// </summary> 935 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index e68f954..8f99dc6 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -59,57 +59,58 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
59 /// <returns>The scene object deserialized. Null on failure.</returns> 59 /// <returns>The scene object deserialized. Null on failure.</returns>
60 public static SceneObjectGroup FromOriginalXmlFormat(string xmlData) 60 public static SceneObjectGroup FromOriginalXmlFormat(string xmlData)
61 { 61 {
62 using (XmlTextReader reader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
63 return FromOriginalXmlFormat(reader);
64 }
65
66 /// <summary>
67 /// Deserialize a scene object from the original xml format
68 /// </summary>
69 /// <param name="xmlData"></param>
70 /// <returns>The scene object deserialized. Null on failure.</returns>
71 public static SceneObjectGroup FromOriginalXmlFormat(XmlTextReader reader)
72 {
62 //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); 73 //m_log.DebugFormat("[SOG]: Starting deserialization of SOG");
63 //int time = System.Environment.TickCount; 74 //int time = System.Environment.TickCount;
64 75
76 SceneObjectGroup sceneObject = null;
77
65 try 78 try
66 { 79 {
67 StringReader sr;
68 XmlTextReader reader;
69 XmlNodeList parts;
70 XmlDocument doc;
71 int linkNum; 80 int linkNum;
72 81
73 doc = new XmlDocument(); 82 reader.ReadToFollowing("RootPart");
74 doc.LoadXml(xmlData); 83 reader.ReadToFollowing("SceneObjectPart");
75 parts = doc.GetElementsByTagName("RootPart"); 84 sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader));
85 reader.ReadToFollowing("OtherParts");
76 86
77 if (parts.Count == 0) 87 if (reader.ReadToDescendant("Part"))
78 throw new Exception("Invalid Xml format - no root part");
79
80 sr = new StringReader(parts[0].InnerXml);
81 reader = new XmlTextReader(sr);
82 SceneObjectGroup sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader));
83 reader.Close();
84 sr.Close();
85
86 parts = doc.GetElementsByTagName("Part");
87
88 for (int i = 0; i < parts.Count; i++)
89 { 88 {
90 sr = new StringReader(parts[i].InnerXml); 89 do
91 reader = new XmlTextReader(sr); 90 {
92 SceneObjectPart part = SceneObjectPart.FromXml(reader); 91 if (reader.ReadToDescendant("SceneObjectPart"))
93 linkNum = part.LinkNum; 92 {
94 sceneObject.AddPart(part); 93 SceneObjectPart part = SceneObjectPart.FromXml(reader);
95 part.LinkNum = linkNum; 94 linkNum = part.LinkNum;
96 part.TrimPermissions(); 95 sceneObject.AddPart(part);
97 reader.Close(); 96 part.LinkNum = linkNum;
98 sr.Close(); 97 part.TrimPermissions();
98 }
99 }
100 while (reader.ReadToNextSibling("Part"));
99 } 101 }
100 102
101 // Script state may, or may not, exist. Not having any, is NOT 103 // Script state may, or may not, exist. Not having any, is NOT
102 // ever a problem. 104 // ever a problem.
103 sceneObject.LoadScriptState(doc); 105 sceneObject.LoadScriptState(reader);
104
105 return sceneObject;
106 } 106 }
107 catch (Exception e) 107 catch (Exception e)
108 { 108 {
109 m_log.ErrorFormat( 109 m_log.ErrorFormat("[SERIALIZER]: Deserialization of xml failed. Exception {0}", e);
110 "[SERIALIZER]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData);
111 return null; 110 return null;
112 } 111 }
112
113 return sceneObject;
113 } 114 }
114 115
115 /// <summary> 116 /// <summary>