From e70cdbc5accc5025ed4e6262ff01ce50bf553141 Mon Sep 17 00:00:00 2001 From: Tedd Hansen Date: Sun, 19 Aug 2007 10:28:27 +0000 Subject: Added event method invoke cache to Executor. "Bind once, Invoke multiple times". Will speed up script event execution considerable. But at the cost of some memory (will be optimized later with RuntimeXHandle). --- OpenSim/Region/ScriptEngine/Common/Executor.cs | 44 ++++++++++++++++--- .../ScriptEngine/DotNetEngine/AppDomainManager.cs | 51 +++++++++------------- .../ScriptEngine/DotNetEngine/ScriptManager.cs | 14 +++++- 3 files changed, 70 insertions(+), 39 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Common/Executor.cs b/OpenSim/Region/ScriptEngine/Common/Executor.cs index ca6459b..dedf00d 100644 --- a/OpenSim/Region/ScriptEngine/Common/Executor.cs +++ b/OpenSim/Region/ScriptEngine/Common/Executor.cs @@ -5,7 +5,7 @@ using System.Reflection; namespace OpenSim.Region.ScriptEngine.Common { - public class Executor: MarshalByRefObject + public class Executor : MarshalByRefObject { /* TODO: * @@ -16,10 +16,12 @@ namespace OpenSim.Region.ScriptEngine.Common */ private IScript m_Script; + private Dictionary Events = new Dictionary(); public Executor(IScript Script) { m_Script = Script; + } public void ExecuteEvent(string FunctionName, object[] args) { @@ -34,23 +36,51 @@ namespace OpenSim.Region.ScriptEngine.Common //} //} - Type type = m_Script.GetType(); - Console.WriteLine("ScriptEngine Executor.ExecuteEvent: \"" + m_Script.State() + "_event_" + FunctionName + "\""); + string EventName = m_Script.State() + "_event_" + FunctionName; + + //type.InvokeMember(EventName, BindingFlags.InvokeMethod, null, m_Script, args); + + Console.WriteLine("ScriptEngine Executor.ExecuteEvent: \"" + EventName + "\""); + + if (Events.ContainsKey(EventName) == false) + { + // Not found, create + Type type = m_Script.GetType(); + try + { + MethodInfo mi = type.GetMethod(EventName); + Events.Add(EventName, mi); + } + catch (Exception e) + { + // Event name not found, cache it as not found + Events.Add(EventName, null); + } + } + + // Get event + MethodInfo ev = null; + Events.TryGetValue(EventName, out ev); + + if (ev == null) // No event by that name! + return; + + // Found try { - type.InvokeMember(m_Script.State() + "_event_" + FunctionName, BindingFlags.InvokeMethod, null, m_Script, args); + // Invoke it + ev.Invoke(m_Script, args); + } catch (Exception e) { // TODO: Send to correct place Console.WriteLine("ScriptEngine Exception attempting to executing script function: " + e.ToString()); } - - } - } + } diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs index 77c859f..1218b19 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs @@ -14,7 +14,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine { public class AppDomainManager { - private int MaxScriptsPerAppDomain = 1; + private int MaxScriptsPerAppDomain = 3; /// /// Internal list of all AppDomains /// @@ -22,7 +22,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine /// /// Structure to keep track of data around AppDomain /// - private struct AppDomainStructure + private class AppDomainStructure { /// /// The AppDomain itself @@ -57,33 +57,25 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine /// Free AppDomain private AppDomainStructure GetFreeAppDomain() { - FreeAppDomains(); - lock(GetLock) { + FreeAppDomains(); // Outsite lock, has its own GetLock + lock (GetLock) + { // Current full? - if (CurrentAD.ScriptsLoaded >= MaxScriptsPerAppDomain) + if (CurrentAD != null && CurrentAD.ScriptsLoaded >= MaxScriptsPerAppDomain) { // Add it to AppDomains list and empty current AppDomains.Add(CurrentAD); - CurrentAD = new AppDomainStructure(); + CurrentAD = null; } // No current - if (CurrentAD.CurrentAppDomain == null) + if (CurrentAD == null) { // Create a new current AppDomain CurrentAD = new AppDomainStructure(); - CurrentAD.ScriptsWaitingUnload = 0; // to avoid compile warning for not in use - CurrentAD.CurrentAppDomain = PrepareNewAppDomain(); - - + CurrentAD.CurrentAppDomain = PrepareNewAppDomain(); } - // Increase number of scripts loaded into this - // TODO: - // - We assume that every time someone wants an AppDomain they will load into it - // if this assumption is wrong we end up with a miscount and will never unload it. - // - - // Return AppDomain + Console.WriteLine("Scripts loaded in this Appdomain: " + CurrentAD.ScriptsLoaded); return CurrentAD; } // lock } @@ -143,19 +135,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine - public OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass LoadScript(string FileName, IScriptHost host) + public OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass LoadScript(string FileName) { - //LSL_BaseClass mbrt = (LSL_BaseClass)FreeAppDomain.CreateInstanceAndUnwrap(FileName, "SecondLife.Script"); - //Console.WriteLine("Base directory: " + AppDomain.CurrentDomain.BaseDirectory); - // * Find next available AppDomain to put it in + // Find next available AppDomain to put it in AppDomainStructure FreeAppDomain = GetFreeAppDomain(); - + if (FreeAppDomain == null) Console.WriteLine("FreeAppDomain == null"); + if (FreeAppDomain.CurrentAppDomain == null) Console.WriteLine("FreeAppDomain.CurrentAppDomain == null"); LSL_BaseClass mbrt = (LSL_BaseClass)FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); - //LSL_BuiltIn_Commands_Interface mbrt = (LSL_BuiltIn_Commands_Interface)FreeAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); //Type mytype = mbrt.GetType(); - //Console.WriteLine("is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); + Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); + // Increase script count in tihs AppDomain FreeAppDomain.ScriptsLoaded++; //mbrt.Start(); @@ -169,7 +160,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine /// Increase "dead script" counter for an AppDomain /// /// - [Obsolete("Needs fixing!!!")] + [Obsolete("Needs fixing, needs a real purpose in life!!!")] public void StopScript(AppDomain ad) { lock (FreeLock) @@ -188,10 +179,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine if (ads.CurrentAppDomain == ad) { // Found it - messy code to increase structure - AppDomainStructure ads2 = ads; - ads2.ScriptsWaitingUnload++; - AppDomains.Remove(ads); - AppDomains.Add(ads2); + //AppDomainStructure ads2 = ads; + ads.ScriptsWaitingUnload++; + //AppDomains.Remove(ads); + //AppDomains.Add(ads2); return; } } // foreach diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs index 9a65b5c..4879fb2 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs @@ -34,6 +34,7 @@ using System.Reflection; using System.Runtime.Remoting; using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes.Scripting; +using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler; using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; using OpenSim.Region.ScriptEngine.Common; @@ -176,7 +177,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine //OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSO.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName); //OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName, ObjectID); - OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName, ObjectID); + long before; + before = GC.GetTotalMemory(true); + LSL_BaseClass Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); + Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); + before = GC.GetTotalMemory(true); + Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); + Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); + before = GC.GetTotalMemory(true); + Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); + Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); // Add it to our temporary active script keeper @@ -184,7 +194,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine SetScript(ObjectID, ScriptID, Script); // We need to give (untrusted) assembly a private instance of BuiltIns // this private copy will contain Read-Only FullScriptID so that it can bring that on to the server whenever needed. - OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL_BuiltIn_Commands LSLB = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL_BuiltIn_Commands(this, ObjectID); + LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(this, ObjectID); // Start the script - giving it BuiltIns Script.Start(LSLB); -- cgit v1.1