Experimental
Moved DotNetScriptEngine configuration to config file. Added option to share script execution threads between regions.ThreadPoolClientBranch
parent
5d6e89eaf9
commit
a9c1f3fdb4
|
@ -69,21 +69,25 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of threads processing event queue
|
/// List of threads processing event queue
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<EventQueueThreadClass> eventQueueThreads = new List<EventQueueThreadClass>();
|
private List<EventQueueThreadClass> eventQueueThreads;// = new List<EventQueueThreadClass>();
|
||||||
private object eventQueueThreadsLock = new object();
|
private object eventQueueThreadsLock;// = new object();
|
||||||
|
|
||||||
|
private static List<EventQueueThreadClass> staticEventQueueThreads;// = new List<EventQueueThreadClass>();
|
||||||
|
private static object staticEventQueueThreadsLock;// = new object();
|
||||||
|
|
||||||
public object queueLock = new object(); // Mutex lock object
|
public object queueLock = new object(); // Mutex lock object
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How many threads to process queue with
|
/// How many threads to process queue with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int numberOfThreads = 2;
|
private int numberOfThreads;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum time one function can use for execution before we perform a thread kill
|
/// Maximum time one function can use for execution before we perform a thread kill
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int maxFunctionExecutionTimems = 50;
|
private int maxFunctionExecutionTimems;
|
||||||
private bool EnforceMaxExecutionTime = true;
|
private bool EnforceMaxExecutionTime;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queue containing events waiting to be executed
|
/// Queue containing events waiting to be executed
|
||||||
|
@ -138,6 +142,36 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
{
|
{
|
||||||
m_ScriptEngine = _ScriptEngine;
|
m_ScriptEngine = _ScriptEngine;
|
||||||
|
|
||||||
|
|
||||||
|
// Create thread pool list and lock object
|
||||||
|
// Determine from config if threads should be dedicated to regions or shared
|
||||||
|
if (m_ScriptEngine.ScriptConfigSource.GetBoolean("PrivateRegionThreads", false))
|
||||||
|
{
|
||||||
|
// PRIVATE THREAD POOL PER REGION
|
||||||
|
eventQueueThreads = new List<EventQueueThreadClass>();
|
||||||
|
eventQueueThreadsLock = new object();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// SHARED THREAD POOL
|
||||||
|
// Crate the objects in statics
|
||||||
|
if (staticEventQueueThreads == null)
|
||||||
|
staticEventQueueThreads = new List<EventQueueThreadClass>();
|
||||||
|
if (staticEventQueueThreadsLock == null)
|
||||||
|
staticEventQueueThreadsLock = new object();
|
||||||
|
|
||||||
|
// Create local reference to them
|
||||||
|
eventQueueThreads = staticEventQueueThreads;
|
||||||
|
eventQueueThreadsLock = staticEventQueueThreadsLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
numberOfThreads = m_ScriptEngine.ScriptConfigSource.GetInt("NumberOfScriptThreads", 2);
|
||||||
|
|
||||||
|
maxFunctionExecutionTimems = m_ScriptEngine.ScriptConfigSource.GetInt("MaxEventExecutionTimeMs", 5000);
|
||||||
|
EnforceMaxExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("EnforceMaxEventExecutionTime", false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Start function max exec time enforcement thread
|
// Start function max exec time enforcement thread
|
||||||
if (EnforceMaxExecutionTime)
|
if (EnforceMaxExecutionTime)
|
||||||
{
|
{
|
||||||
|
@ -150,9 +184,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
//
|
//
|
||||||
// Start event queue processing threads (worker threads)
|
// Start event queue processing threads (worker threads)
|
||||||
//
|
//
|
||||||
|
|
||||||
lock (eventQueueThreadsLock)
|
lock (eventQueueThreadsLock)
|
||||||
{
|
{
|
||||||
for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++)
|
for (int ThreadCount = eventQueueThreads.Count; ThreadCount <= numberOfThreads; ThreadCount++)
|
||||||
{
|
{
|
||||||
StartNewThreadClass();
|
StartNewThreadClass();
|
||||||
}
|
}
|
||||||
|
@ -315,7 +350,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AbortThreadClass(EventQueueThreadClass threadClass)
|
private void AbortThreadClass(EventQueueThreadClass threadClass)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -326,12 +361,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
Console.WriteLine("Could you please report this to Tedd:");
|
Console.WriteLine("Could you please report this to Tedd:");
|
||||||
Console.WriteLine("Script thread execution timeout kill ended in exception: " + ex.ToString());
|
Console.WriteLine("Script thread execution timeout kill ended in exception: " + ex.ToString());
|
||||||
}
|
}
|
||||||
|
m_ScriptEngine.Log.Debug("DotNetEngine", "Killed script execution thread, count: " + eventQueueThreads.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartNewThreadClass()
|
private void StartNewThreadClass()
|
||||||
{
|
{
|
||||||
EventQueueThreadClass eqtc = new EventQueueThreadClass(this);
|
EventQueueThreadClass eqtc = new EventQueueThreadClass(this);
|
||||||
eventQueueThreads.Add(eqtc);
|
eventQueueThreads.Add(eqtc);
|
||||||
|
m_ScriptEngine.Log.Debug("DotNetEngine", "Started new script execution thread, count: " + eventQueueThreads.Count);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Environment.Scenes.Scripting;
|
using OpenSim.Region.Environment.Scenes.Scripting;
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How many ms to sleep if queue is empty
|
/// How many ms to sleep if queue is empty
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int nothingToDoSleepms = 50;
|
private int nothingToDoSleepms;// = 50;
|
||||||
|
|
||||||
public DateTime LastExecutionStarted;
|
public DateTime LastExecutionStarted;
|
||||||
public bool InExecution = false;
|
public bool InExecution = false;
|
||||||
|
@ -28,6 +29,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
public EventQueueThreadClass(EventQueueManager eqm)
|
public EventQueueThreadClass(EventQueueManager eqm)
|
||||||
{
|
{
|
||||||
eventQueueManager = eqm;
|
eventQueueManager = eqm;
|
||||||
|
nothingToDoSleepms = eqm.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50);
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +185,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
}
|
}
|
||||||
catch (ThreadAbortException tae)
|
catch (ThreadAbortException tae)
|
||||||
{
|
{
|
||||||
throw tae;
|
eventQueueManager.m_ScriptEngine.Log.Notice("ScriptEngine", "ThreadAbortException while executing function.");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,10 +51,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
public AppDomainManager m_AppDomainManager;
|
public AppDomainManager m_AppDomainManager;
|
||||||
public LSLLongCmdHandler m_LSLLongCmdHandler;
|
public LSLLongCmdHandler m_LSLLongCmdHandler;
|
||||||
|
|
||||||
|
public IConfigSource ConfigSource;
|
||||||
|
public IConfig ScriptConfigSource;
|
||||||
|
public abstract string ScriptConfigSourceName { get; }
|
||||||
|
|
||||||
public ScriptManager GetScriptManager()
|
public ScriptManager GetScriptManager()
|
||||||
{
|
{
|
||||||
return _GetScriptManager();
|
return _GetScriptManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract ScriptManager _GetScriptManager();
|
public abstract ScriptManager _GetScriptManager();
|
||||||
|
|
||||||
private LogBase m_log;
|
private LogBase m_log;
|
||||||
|
@ -74,6 +79,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
{
|
{
|
||||||
World = Sceneworld;
|
World = Sceneworld;
|
||||||
m_log = logger;
|
m_log = logger;
|
||||||
|
ScriptConfigSource = ConfigSource.Configs[ScriptConfigSourceName];
|
||||||
|
|
||||||
Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing");
|
Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing");
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||||
// We need to override a few things for our DotNetEngine
|
// We need to override a few things for our DotNetEngine
|
||||||
public override void Initialise(Scene scene, IConfigSource config)
|
public override void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
|
ConfigSource = config;
|
||||||
InitializeEngine(scene, MainLog.Instance, true, GetScriptManager());
|
InitializeEngine(scene, MainLog.Instance, true, GetScriptManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,5 +47,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||||
{
|
{
|
||||||
return new ScriptManager(this);
|
return new ScriptManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ScriptConfigSourceName
|
||||||
|
{
|
||||||
|
get { return "ScriptEngine.DotNetEngine"; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -51,5 +51,11 @@ namespace OpenSim.Region.ScriptEngine.LSOEngine
|
||||||
{
|
{
|
||||||
return new ScriptManager(this);
|
return new ScriptManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ScriptConfigSourceName
|
||||||
|
{
|
||||||
|
get { return "ScriptEngine.LSOEngine"; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -114,3 +114,35 @@ shout_distance = 100
|
||||||
; send a Sun update ever frame_rate # of frames. A lower number will
|
; send a Sun update ever frame_rate # of frames. A lower number will
|
||||||
; make for smoother sun transition at the cost of network
|
; make for smoother sun transition at the cost of network
|
||||||
;frame_rate = 100
|
;frame_rate = 100
|
||||||
|
|
||||||
|
[ScriptEngine.DotNetEngine]
|
||||||
|
|
||||||
|
; When a script receives an event the event is queued.
|
||||||
|
; Any free thread will start executing this event. One script can only have one event executed simultaneously.
|
||||||
|
; If you have only one thread, and one script has a loop or does a lot of work, then no other scripts can run at the same time.
|
||||||
|
; Same if you have 10 threads, then only 10 scripts can be run simultaneously.
|
||||||
|
; But because most scripts exit after their task, the threads are free to go on to the next script.
|
||||||
|
|
||||||
|
; Number of threads to use for script event execution
|
||||||
|
; Threads are shared across all regions
|
||||||
|
NumberOfScriptThreads=2
|
||||||
|
|
||||||
|
; Should the script threads be private for each region?
|
||||||
|
; true: Each region will get <NumberOfScriptThreads> dedicated to scripts within that region
|
||||||
|
; Number of threads will be <NumberOfScriptThreads>*<NumberOfRegions>
|
||||||
|
; false: All regions share <NumberOfScriptThreads> for all their scripts
|
||||||
|
PrivateRegionThreads=false
|
||||||
|
|
||||||
|
; How long MAX should a script be allowed to run?
|
||||||
|
; Do not set this too low (like 50ms) as there are some time wasted in simply executing a function
|
||||||
|
; There is also a small speed penalty for every kill that is made
|
||||||
|
MaxEventExecutionTimeMs=5000
|
||||||
|
|
||||||
|
; Should we enable the max script event execution thread to look for scripts that exceed their timeslice?
|
||||||
|
EnforceMaxEventExecutionTime=true
|
||||||
|
|
||||||
|
; If no scripts have executed in this pass how long should we sleep before checking again
|
||||||
|
; Impact:
|
||||||
|
; Too low and you will waste lots of CPU
|
||||||
|
; Too high and people touching object or similar will have to wait up to this amount of time before script responding
|
||||||
|
SleepTimeIfNoScriptExecutionMs=50
|
||||||
|
|
Loading…
Reference in New Issue