aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs123
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs31
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs26
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs54
8 files changed, 174 insertions, 114 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 6fba249..e955a58 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -503,7 +503,11 @@ namespace OpenSim
503 string currentCommand; 503 string currentCommand;
504 while ((currentCommand = readFile.ReadLine()) != null) 504 while ((currentCommand = readFile.ReadLine()) != null)
505 { 505 {
506 if (currentCommand != String.Empty) 506 currentCommand = currentCommand.Trim();
507 if (!(currentCommand == ""
508 || currentCommand.StartsWith(";")
509 || currentCommand.StartsWith("//")
510 || currentCommand.StartsWith("#")))
507 { 511 {
508 m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'"); 512 m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'");
509 m_console.RunCommand(currentCommand); 513 m_console.RunCommand(currentCommand);
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index c303d6d..61d604f 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -26,8 +26,10 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.IO; 31using System.IO;
32using System.Linq;
31using System.Reflection; 33using System.Reflection;
32using System.Security; 34using System.Security;
33using log4net; 35using log4net;
@@ -45,8 +47,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
45 { 47 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 49
48 private delegate void LookupUUIDS(List<UUID> uuidLst);
49
50 public Scene Scene { get; private set; } 50 public Scene Scene { get; private set; }
51 public IUserManagement UserManager { get; private set; } 51 public IUserManagement UserManager { get; private set; }
52 52
@@ -876,98 +876,77 @@ namespace OpenSim.Region.CoreModules.World.Estate
876 if (!Scene.Permissions.CanIssueEstateCommand(remoteClient.AgentId, false)) 876 if (!Scene.Permissions.CanIssueEstateCommand(remoteClient.AgentId, false))
877 return; 877 return;
878 878
879 Dictionary<uint, float> SceneData = new Dictionary<uint,float>(); 879 Dictionary<uint, float> sceneData = null;
880 List<UUID> uuidNameLookupList = new List<UUID>(); 880 List<UUID> uuidNameLookupList = new List<UUID>();
881 881
882 if (reportType == 1) 882 if (reportType == 1)
883 { 883 {
884 SceneData = Scene.PhysicsScene.GetTopColliders(); 884 sceneData = Scene.PhysicsScene.GetTopColliders();
885 } 885 }
886 else if (reportType == 0) 886 else if (reportType == 0)
887 { 887 {
888 SceneData = Scene.SceneGraph.GetTopScripts(); 888 IScriptModule scriptModule = Scene.RequestModuleInterface<IScriptModule>();
889
890 if (scriptModule != null)
891 sceneData = scriptModule.GetObjectScriptsExecutionTimes();
889 } 892 }
890 893
891 List<LandStatReportItem> SceneReport = new List<LandStatReportItem>(); 894 List<LandStatReportItem> SceneReport = new List<LandStatReportItem>();
892 lock (SceneData) 895 if (sceneData != null)
893 { 896 {
894 foreach (uint obj in SceneData.Keys) 897 var sortedSceneData
898 = sceneData.Select(
899 item => new { Measurement = item.Value, Part = Scene.GetSceneObjectPart(item.Key) });
900
901 sortedSceneData.OrderBy(item => item.Measurement);
902
903 int items = 0;
904
905 foreach (var entry in sortedSceneData)
895 { 906 {
896 SceneObjectPart prt = Scene.GetSceneObjectPart(obj); 907 // The object may have been deleted since we received the data.
897 if (prt != null) 908 if (entry.Part == null)
909 continue;
910
911 // Don't show scripts that haven't executed or where execution time is below one microsecond in
912 // order to produce a more readable report.
913 if (entry.Measurement < 0.001)
914 continue;
915
916 items++;
917 SceneObjectGroup so = entry.Part.ParentGroup;
918
919 LandStatReportItem lsri = new LandStatReportItem();
920 lsri.LocationX = so.AbsolutePosition.X;
921 lsri.LocationY = so.AbsolutePosition.Y;
922 lsri.LocationZ = so.AbsolutePosition.Z;
923 lsri.Score = entry.Measurement;
924 lsri.TaskID = so.UUID;
925 lsri.TaskLocalID = so.LocalId;
926 lsri.TaskName = entry.Part.Name;
927 lsri.OwnerName = UserManager.GetUserName(so.OwnerID);
928
929 if (filter.Length != 0)
898 { 930 {
899 SceneObjectGroup sog = prt.ParentGroup; 931 if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter)))
900 LandStatReportItem lsri = new LandStatReportItem();
901 lsri.LocationX = sog.AbsolutePosition.X;
902 lsri.LocationY = sog.AbsolutePosition.Y;
903 lsri.LocationZ = sog.AbsolutePosition.Z;
904 lsri.Score = SceneData[obj];
905 lsri.TaskID = sog.UUID;
906 lsri.TaskLocalID = sog.LocalId;
907 lsri.TaskName = sog.GetPartName(obj);
908 lsri.OwnerName = "waiting";
909 lock (uuidNameLookupList)
910 uuidNameLookupList.Add(sog.OwnerID);
911
912 if (filter.Length != 0)
913 { 932 {
914 if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter)))
915 {
916 }
917 else
918 {
919 continue;
920 }
921 } 933 }
922 934 else
923 SceneReport.Add(lsri); 935 {
936 continue;
937 }
924 } 938 }
939
940 SceneReport.Add(lsri);
941
942 if (items >= 100)
943 break;
925 } 944 }
926 } 945 }
927 946
928 remoteClient.SendLandStatReply(reportType, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray()); 947 remoteClient.SendLandStatReply(reportType, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray());
929
930 if (uuidNameLookupList.Count > 0)
931 LookupUUID(uuidNameLookupList);
932 } 948 }
933 949
934 private static void LookupUUIDSCompleted(IAsyncResult iar)
935 {
936 LookupUUIDS icon = (LookupUUIDS)iar.AsyncState;
937 icon.EndInvoke(iar);
938 }
939
940 private void LookupUUID(List<UUID> uuidLst)
941 {
942 LookupUUIDS d = LookupUUIDsAsync;
943
944 d.BeginInvoke(uuidLst,
945 LookupUUIDSCompleted,
946 d);
947 }
948
949 private void LookupUUIDsAsync(List<UUID> uuidLst)
950 {
951 UUID[] uuidarr;
952
953 lock (uuidLst)
954 {
955 uuidarr = uuidLst.ToArray();
956 }
957
958 for (int i = 0; i < uuidarr.Length; i++)
959 {
960 // string lookupname = m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]);
961
962 IUserManagement userManager = Scene.RequestModuleInterface<IUserManagement>();
963 if (userManager != null)
964 userManager.GetUserName(uuidarr[i]);
965
966 // we drop it. It gets cached though... so we're ready for the next request.
967 // diva commnent 11/21/2010: uh?!? wft?
968 // justincc comment 21/01/2011: A side effect of userManager.GetUserName() I presume.
969 }
970 }
971 #endregion 950 #endregion
972 951
973 #region Outgoing Packets 952 #region Outgoing Packets
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 18c45dd..9cab2e1 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31 32
32namespace OpenSim.Region.Framework.Interfaces 33namespace OpenSim.Region.Framework.Interfaces
@@ -74,5 +75,14 @@ namespace OpenSim.Region.Framework.Interfaces
74 /// Starts the processing threads. 75 /// Starts the processing threads.
75 /// </summary> 76 /// </summary>
76 void StartProcessing(); 77 void StartProcessing();
78
79 /// <summary>
80 /// Get the execution times of all scripts in each object.
81 /// </summary>
82 /// <returns>
83 /// A dictionary where the key is the root object ID of a linkset
84 /// and the value is a representative execution time in milliseconds of all scripts in that linkset.
85 /// </returns>
86 Dictionary<uint, float> GetObjectScriptsExecutionTimes();
77 } 87 }
78} 88} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index bc3400a..5c542d6 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -733,6 +733,7 @@ namespace OpenSim.Region.Framework.Scenes
733 #endregion 733 #endregion
734 734
735 #region Get Methods 735 #region Get Methods
736
736 /// <summary> 737 /// <summary>
737 /// Get the controlling client for the given avatar, if there is one. 738 /// Get the controlling client for the given avatar, if there is one.
738 /// 739 ///
@@ -1074,36 +1075,6 @@ namespace OpenSim.Region.Framework.Scenes
1074 return Entities.GetEntities(); 1075 return Entities.GetEntities();
1075 } 1076 }
1076 1077
1077 public Dictionary<uint, float> GetTopScripts()
1078 {
1079 Dictionary<uint, float> topScripts = new Dictionary<uint, float>();
1080
1081 EntityBase[] EntityList = GetEntities();
1082 int limit = 0;
1083 foreach (EntityBase ent in EntityList)
1084 {
1085 if (ent is SceneObjectGroup)
1086 {
1087 SceneObjectGroup grp = (SceneObjectGroup)ent;
1088 if ((grp.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
1089 {
1090 if (grp.scriptScore >= 0.01)
1091 {
1092 topScripts.Add(grp.LocalId, grp.scriptScore);
1093 limit++;
1094 if (limit >= 100)
1095 {
1096 break;
1097 }
1098 }
1099 grp.scriptScore = 0;
1100 }
1101 }
1102 }
1103
1104 return topScripts;
1105 }
1106
1107 #endregion 1078 #endregion
1108 1079
1109 #region Other Methods 1080 #region Other Methods
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 878476e..afb5ccf 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -229,8 +229,6 @@ namespace OpenSim.Region.Framework.Scenes
229 get { return RootPart.VolumeDetectActive; } 229 get { return RootPart.VolumeDetectActive; }
230 } 230 }
231 231
232 public float scriptScore;
233
234 private Vector3 lastPhysGroupPos; 232 private Vector3 lastPhysGroupPos;
235 private Quaternion lastPhysGroupRot; 233 private Quaternion lastPhysGroupRot;
236 234
@@ -1184,12 +1182,7 @@ namespace OpenSim.Region.Framework.Scenes
1184 1182
1185 public void AddScriptLPS(int count) 1183 public void AddScriptLPS(int count)
1186 { 1184 {
1187 if (scriptScore + count >= float.MaxValue - count) 1185 m_scene.SceneGraph.AddToScriptLPS(count);
1188 scriptScore = 0;
1189
1190 scriptScore += (float)count;
1191 SceneGraph d = m_scene.SceneGraph;
1192 d.AddToScriptLPS(count);
1193 } 1186 }
1194 1187
1195 public void AddActiveScriptCount(int count) 1188 public void AddActiveScriptCount(int count)
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index 8762642..b04f6b6 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -78,12 +78,38 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
78 /// </summary> 78 /// </summary>
79 string State { get; set; } 79 string State { get; set; }
80 80
81 /// <summary>
82 /// Time the script was last started
83 /// </summary>
84 DateTime TimeStarted { get; }
85
86 /// <summary>
87 /// Tick the last measurement period was started.
88 /// </summary>
89 long MeasurementPeriodTickStart { get; }
90
91 /// <summary>
92 /// Ticks spent executing in the last measurement period.
93 /// </summary>
94 long MeasurementPeriodExecutionTime { get; }
95
81 IScriptEngine Engine { get; } 96 IScriptEngine Engine { get; }
82 UUID AppDomain { get; set; } 97 UUID AppDomain { get; set; }
83 string PrimName { get; } 98 string PrimName { get; }
84 string ScriptName { get; } 99 string ScriptName { get; }
85 UUID ItemID { get; } 100 UUID ItemID { get; }
86 UUID ObjectID { get; } 101 UUID ObjectID { get; }
102
103 /// <summary>
104 /// UUID of the root object for the linkset that the script is in.
105 /// </summary>
106 UUID RootObjectID { get; }
107
108 /// <summary>
109 /// Local id of the root object for the linkset that the script is in.
110 /// </summary>
111 uint RootLocalID { get; }
112
87 uint LocalID { get; } 113 uint LocalID { get; }
88 UUID AssetID { get; } 114 UUID AssetID { get; }
89 Queue EventQueue { get; } 115 Queue EventQueue { get; }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 968351b..6e36742 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -164,6 +164,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
164 164
165 public uint LocalID { get; private set; } 165 public uint LocalID { get; private set; }
166 166
167 public UUID RootObjectID { get; private set; }
168
169 public uint RootLocalID { get; private set; }
170
167 public UUID AssetID { get; private set; } 171 public UUID AssetID { get; private set; }
168 172
169 public Queue EventQueue { get; private set; } 173 public Queue EventQueue { get; private set; }
@@ -172,6 +176,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
172 176
173 public TaskInventoryItem ScriptTask { get; private set; } 177 public TaskInventoryItem ScriptTask { get; private set; }
174 178
179 public DateTime TimeStarted { get; private set; }
180
181 public long MeasurementPeriodTickStart { get; private set; }
182
183 public long MeasurementPeriodExecutionTime { get; private set; }
184
185 public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute;
186
175 public void ClearQueue() 187 public void ClearQueue()
176 { 188 {
177 m_TimerQueued = false; 189 m_TimerQueued = false;
@@ -190,6 +202,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
190 Engine = engine; 202 Engine = engine;
191 LocalID = part.LocalId; 203 LocalID = part.LocalId;
192 ObjectID = part.UUID; 204 ObjectID = part.UUID;
205 RootLocalID = part.ParentGroup.LocalId;
206 RootObjectID = part.ParentGroup.UUID;
193 ItemID = itemID; 207 ItemID = itemID;
194 AssetID = assetID; 208 AssetID = assetID;
195 PrimName = primName; 209 PrimName = primName;
@@ -458,6 +472,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
458 472
459 Running = true; 473 Running = true;
460 474
475 TimeStarted = DateTime.Now;
476 MeasurementPeriodTickStart = Util.EnvironmentTickCount();
477 MeasurementPeriodExecutionTime = 0;
478
461 if (EventQueue.Count > 0) 479 if (EventQueue.Count > 0)
462 { 480 {
463 if (m_CurrentWorkItem == null) 481 if (m_CurrentWorkItem == null)
@@ -710,8 +728,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
710 m_EventStart = DateTime.Now; 728 m_EventStart = DateTime.Now;
711 m_InEvent = true; 729 m_InEvent = true;
712 730
731 int start = Util.EnvironmentTickCount();
732
733 // Reset the measurement period when we reach the end of the current one.
734 if (start - MeasurementPeriodTickStart > MaxMeasurementPeriod)
735 MeasurementPeriodTickStart = start;
736
713 m_Script.ExecuteEvent(State, data.EventName, data.Params); 737 m_Script.ExecuteEvent(State, data.EventName, data.Params);
714 738
739 MeasurementPeriodExecutionTime += Util.EnvironmentTickCount() - start;
740
715 m_InEvent = false; 741 m_InEvent = false;
716 m_CurrentEvent = String.Empty; 742 m_CurrentEvent = String.Empty;
717 743
@@ -720,7 +746,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
720 // This will be the very first event we deliver 746 // This will be the very first event we deliver
721 // (state_entry) in default state 747 // (state_entry) in default state
722 // 748 //
723
724 SaveState(m_Assembly); 749 SaveState(m_Assembly);
725 750
726 m_SaveState = false; 751 m_SaveState = false;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 105d97d..3697f78 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -1083,7 +1083,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1083 1083
1084 if (!m_PrimObjects[localID].Contains(itemID)) 1084 if (!m_PrimObjects[localID].Contains(itemID))
1085 m_PrimObjects[localID].Add(itemID); 1085 m_PrimObjects[localID].Add(itemID);
1086
1087 } 1086 }
1088 1087
1089 if (!m_Assemblies.ContainsKey(assetID)) 1088 if (!m_Assemblies.ContainsKey(assetID))
@@ -1891,6 +1890,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1891 } 1890 }
1892 } 1891 }
1893 1892
1893 public Dictionary<uint, float> GetObjectScriptsExecutionTimes()
1894 {
1895 long tickNow = Util.EnvironmentTickCount();
1896 Dictionary<uint, float> topScripts = new Dictionary<uint, float>();
1897
1898 lock (m_Scripts)
1899 {
1900 foreach (IScriptInstance si in m_Scripts.Values)
1901 {
1902 if (!topScripts.ContainsKey(si.LocalID))
1903 topScripts[si.RootLocalID] = 0;
1904
1905// long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
1906// float framesElapsed = ticksElapsed / (18.1818 * TimeSpan.TicksPerMillisecond);
1907
1908 // Execution time of the script adjusted by it's measurement period to make scripts started at
1909 // different times comparable.
1910// float adjustedExecutionTime
1911// = (float)si.MeasurementPeriodExecutionTime
1912// / ((float)(tickNow - si.MeasurementPeriodTickStart) / ScriptInstance.MaxMeasurementPeriod)
1913// / TimeSpan.TicksPerMillisecond;
1914
1915 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
1916
1917 // Avoid divide by zerp
1918 if (ticksElapsed == 0)
1919 ticksElapsed = 1;
1920
1921 // Scale execution time to the ideal 55 fps frame time for these reasons.
1922 //
1923 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
1924 // 'script execution time per frame', which is the original purpose of this value.
1925 //
1926 // 2) Giving the raw execution times is misleading since scripts start at different times, making
1927 // it impossible to compare scripts.
1928 //
1929 // 3) Scaling the raw execution time to the time that the script has been running is better but
1930 // is still misleading since a script that has just been rezzed may appear to have been running
1931 // for much longer.
1932 //
1933 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
1934 // since the figure does not represent actual execution time and very hard running scripts will
1935 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
1936 float adjustedExecutionTime
1937 = ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
1938
1939 topScripts[si.RootLocalID] += adjustedExecutionTime;
1940 }
1941 }
1942
1943 return topScripts;
1944 }
1945
1894 public void SuspendScript(UUID itemID) 1946 public void SuspendScript(UUID itemID)
1895 { 1947 {
1896// m_log.DebugFormat("[XEngine]: Received request to suspend script with ID {0}", itemID); 1948// m_log.DebugFormat("[XEngine]: Received request to suspend script with ID {0}", itemID);