mirror of
https://github.com/opensim/opensim.git
synced 2026-05-16 03:36:04 +08:00
Report "Script Execution Time" as the time spent executing the script in the last 30 seconds. Use a sliding window to calculate this.
Notes: - This metric provides a better indication of which scripts are taking up a lot of CPU (and therefore should be optimized). - Previously the execution time was reset to 0 in every new measurement period, causing the reported time to fluctuate for no reason. This has been fixed by using a sliding window.
This commit is contained in:
@@ -109,14 +109,9 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||
DateTime TimeStarted { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Tick the last measurement period was started.
|
||||
/// Collects information about how long the script was executed.
|
||||
/// </summary>
|
||||
long MeasurementPeriodTickStart { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ticks spent executing in the last measurement period.
|
||||
/// </summary>
|
||||
long MeasurementPeriodExecutionTime { get; }
|
||||
MetricsCollectorTime ExecutionTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Scene part in which this script instance is contained.
|
||||
|
||||
@@ -199,11 +199,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
|
||||
public DateTime TimeStarted { get; private set; }
|
||||
|
||||
public long MeasurementPeriodTickStart { get; private set; }
|
||||
public MetricsCollectorTime ExecutionTime { get; private set; }
|
||||
|
||||
public long MeasurementPeriodExecutionTime { get; private set; }
|
||||
|
||||
public static readonly int MaxMeasurementPeriod = 30 * 1000; // show the *recent* time used by the script, to find currently active scripts
|
||||
private static readonly int MeasurementWindow = 30 * 1000; // show the *recent* time used by the script, to find currently active scripts
|
||||
|
||||
private bool m_coopTermination;
|
||||
|
||||
@@ -246,6 +244,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
|
||||
m_SaveState = StatePersistedHere;
|
||||
|
||||
ExecutionTime = new MetricsCollectorTime(MeasurementWindow, 10);
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[SCRIPT INSTANCE]: Instantiated script instance {0} (id {1}) in part {2} (id {3}) in object {4} attached avatar {5} in {6}",
|
||||
// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, m_AttachedAvatar, Engine.World.Name);
|
||||
@@ -505,8 +505,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
Running = true;
|
||||
|
||||
TimeStarted = DateTime.Now;
|
||||
MeasurementPeriodTickStart = Util.EnvironmentTickCount();
|
||||
MeasurementPeriodExecutionTime = 0;
|
||||
|
||||
// Note: we don't reset ExecutionTime. The reason is that runaway scripts are stopped and restarted
|
||||
// automatically, and we *do* want to show that they had high CPU in that case. If we had reset
|
||||
// ExecutionTime here then runaway scripts, paradoxically, would never show up in the "Top Scripts" dialog.
|
||||
|
||||
if (EventQueue.Count > 0)
|
||||
{
|
||||
@@ -832,20 +834,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
m_EventStart = DateTime.Now;
|
||||
m_InEvent = true;
|
||||
|
||||
// Reset the measurement period when we reach the end of the current one.
|
||||
if (Util.EnvironmentTickCountSubtract((int)MeasurementPeriodTickStart) > MaxMeasurementPeriod)
|
||||
{
|
||||
MeasurementPeriodTickStart = Util.EnvironmentTickCount();
|
||||
MeasurementPeriodExecutionTime = 0;
|
||||
}
|
||||
Stopwatch timer = new Stopwatch();
|
||||
timer.Start();
|
||||
|
||||
Stopwatch executionTime = new Stopwatch();
|
||||
executionTime.Start();
|
||||
|
||||
m_Script.ExecuteEvent(State, data.EventName, data.Params);
|
||||
|
||||
executionTime.Stop();
|
||||
MeasurementPeriodExecutionTime += executionTime.ElapsedMilliseconds;
|
||||
timer.Stop();
|
||||
ExecutionTime.AddSample(timer);
|
||||
|
||||
m_InEvent = false;
|
||||
m_CurrentEvent = String.Empty;
|
||||
|
||||
@@ -2343,7 +2343,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
|
||||
public Dictionary<uint, float> GetObjectScriptsExecutionTimes()
|
||||
{
|
||||
long tickNow = Util.EnvironmentTickCount();
|
||||
Dictionary<uint, float> topScripts = new Dictionary<uint, float>();
|
||||
|
||||
lock (m_Scripts)
|
||||
@@ -2353,7 +2352,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
if (!topScripts.ContainsKey(si.LocalID))
|
||||
topScripts[si.RootLocalID] = 0;
|
||||
|
||||
topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow);
|
||||
topScripts[si.RootLocalID] += GetExectionTime(si);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2367,7 +2366,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
return 0.0f;
|
||||
}
|
||||
float time = 0.0f;
|
||||
long tickNow = Util.EnvironmentTickCount();
|
||||
IScriptInstance si;
|
||||
// Calculate the time for all scripts that this engine is executing
|
||||
// Ignore any others
|
||||
@@ -2376,36 +2374,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
si = GetInstance(id);
|
||||
if (si != null && si.Running)
|
||||
{
|
||||
time += CalculateAdjustedExectionTime(si, tickNow);
|
||||
time += GetExectionTime(si);
|
||||
}
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow)
|
||||
private float GetExectionTime(IScriptInstance si)
|
||||
{
|
||||
long ticksElapsed = Util.EnvironmentTickCountSubtract((int)tickNow, (int)si.MeasurementPeriodTickStart);
|
||||
|
||||
// Avoid divide by zero
|
||||
if (ticksElapsed == 0)
|
||||
ticksElapsed = 1;
|
||||
|
||||
// Scale execution time to the ideal 55 fps frame time for these reasons.
|
||||
//
|
||||
// 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
|
||||
// 'script execution time per frame', which is the original purpose of this value.
|
||||
//
|
||||
// 2) Giving the raw execution times is misleading since scripts start at different times, making
|
||||
// it impossible to compare scripts.
|
||||
//
|
||||
// 3) Scaling the raw execution time to the time that the script has been running is better but
|
||||
// is still misleading since a script that has just been rezzed may appear to have been running
|
||||
// for much longer.
|
||||
//
|
||||
// 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
|
||||
// since the figure does not represent actual execution time and very hard running scripts will
|
||||
// never exceed 18ms (though this is a very high number for script execution so is a warning sign).
|
||||
return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
|
||||
return (float)si.ExecutionTime.GetSumTime().TotalMilliseconds;
|
||||
}
|
||||
|
||||
public void SuspendScript(UUID itemID)
|
||||
|
||||
Reference in New Issue
Block a user