Experimental

Moved DotNetScriptEngine configuration to config file.
Added option to share script execution threads between regions.
ThreadPoolClientBranch
Tedd Hansen 2008-02-01 20:12:25 +00:00
parent 5d6e89eaf9
commit a9c1f3fdb4
6 changed files with 99 additions and 9 deletions

View File

@ -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);
} }
} }
} }

View File

@ -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)
{ {

View File

@ -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");

View File

@ -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"; }
}
} }
} }

View File

@ -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"; }
}
} }
} }

View File

@ -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