From 33448e4ba83b590e0e7e340faf3d7f2cef80c611 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Mon, 26 Oct 2009 07:50:25 -0700 Subject: Optimizations --- .../ScriptEngine/Shared/CodeTools/Compiler.cs | 156 ++++++++++----------- 1 file changed, 72 insertions(+), 84 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs') diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index fe26429..d781a1a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -74,7 +74,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools private string FilePrefix; private string ScriptEnginesPath = "ScriptEngines"; // mapping between LSL and C# line/column numbers - private Dictionary, KeyValuePair> m_positionMap; private ICodeConverter LSL_Converter; private List m_warnings = new List(); @@ -91,6 +90,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools private static UInt64 scriptCompileCounter = 0; // And a counter public IScriptEngine m_scriptEngine; + private Dictionary, KeyValuePair>> m_lineMaps = + new Dictionary, KeyValuePair>>(); + public Compiler(IScriptEngine scriptEngine) { m_scriptEngine = scriptEngine; @@ -271,16 +273,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools /// /// LSL script /// Filename to .dll assembly - public object PerformScriptCompile(string Script, string asset, UUID ownerUUID) + public void PerformScriptCompile(string Script, string asset, UUID ownerUUID, + out string assembly, out Dictionary, KeyValuePair> linemap) { - m_positionMap = null; + linemap = null; m_warnings.Clear(); - - string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( + + assembly = Path.Combine(ScriptEnginesPath, Path.Combine( m_scriptEngine.World.RegionInfo.RegionID.ToString(), FilePrefix + "_compiled_" + asset + ".dll")); -// string OutFile = Path.Combine(ScriptEnginesPath, -// FilePrefix + "_compiled_" + asset + ".dll"); if (!Directory.Exists(ScriptEnginesPath)) { @@ -305,51 +306,53 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } } - if (Script == String.Empty) + // Don't recompile if we already have it + // Performing 3 file exists tests for every script can still be slow + if (File.Exists(assembly) && File.Exists(assembly + ".text") && File.Exists(assembly + ".map")) { - if (File.Exists(OutFile)) - return OutFile; - - throw new Exception("Cannot find script assembly and no script text present"); + // If we have already read this linemap file, then it will be in our dictionary. + // Don't build another copy of the dictionary (saves memory) and certainly + // don't keep reading the same file from disk multiple times. + if (!m_lineMaps.ContainsKey(assembly)) + m_lineMaps[assembly] = ReadMapFile(assembly + ".map"); + linemap = m_lineMaps[assembly]; + return; } - // Don't recompile if we already have it - // - if (File.Exists(OutFile) && File.Exists(OutFile+".text") && File.Exists(OutFile+".map")) + if (Script == String.Empty) { - ReadMapFile(OutFile+".map"); - return OutFile; + throw new Exception("Cannot find script assembly and no script text present"); } - enumCompileType l = DefaultCompileLanguage; + enumCompileType language = DefaultCompileLanguage; if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture)) - l = enumCompileType.cs; + language = enumCompileType.cs; if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture)) { - l = enumCompileType.vb; + language = enumCompileType.vb; // We need to remove //vb, it won't compile with that Script = Script.Substring(4, Script.Length - 4); } if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture)) - l = enumCompileType.lsl; + language = enumCompileType.lsl; if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture)) - l = enumCompileType.js; + language = enumCompileType.js; if (Script.StartsWith("//yp", true, CultureInfo.InvariantCulture)) - l = enumCompileType.yp; + language = enumCompileType.yp; - if (!AllowedCompilers.ContainsKey(l.ToString())) + if (!AllowedCompilers.ContainsKey(language.ToString())) { // Not allowed to compile to this language! string errtext = String.Empty; - errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!"; + errtext += "The compiler for language \"" + language.ToString() + "\" is not in list of allowed compilers. Script will not be executed!"; throw new Exception(errtext); } - if (m_scriptEngine.World.Permissions.CanCompileScript(ownerUUID, (int)l) == false) { + if (m_scriptEngine.World.Permissions.CanCompileScript(ownerUUID, (int)language) == false) { // Not allowed to compile to this language! string errtext = String.Empty; errtext += ownerUUID + " is not in list of allowed users for this scripting language. Script will not be executed!"; @@ -358,7 +361,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools string compileScript = Script; - if (l == enumCompileType.lsl) + if (language == enumCompileType.lsl) { // Its LSL, convert it to C# LSL_Converter = (ICodeConverter)new CSCodeGenerator(); @@ -370,16 +373,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools AddWarning(warning); } - m_positionMap = ((CSCodeGenerator) LSL_Converter).PositionMap; + linemap = ((CSCodeGenerator) LSL_Converter).PositionMap; + // Write the linemap to a file and save it in our dictionary for next time. + m_lineMaps[assembly] = linemap; + WriteMapFile(assembly + ".map", linemap); } - if (l == enumCompileType.yp) + if (language == enumCompileType.yp) { // Its YP, convert it to C# compileScript = YP_Converter.Convert(Script); } - switch (l) + switch (language) { case enumCompileType.cs: case enumCompileType.lsl: @@ -396,7 +402,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools break; } - return CompileFromDotNetText(compileScript, l, asset); + assembly = CompileFromDotNetText(compileScript, language, asset, assembly); + return; } public string[] GetWarnings() @@ -468,18 +475,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools /// /// CS script /// Filename to .dll assembly - internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset) + internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset, string assembly) { string ext = "." + lang.ToString(); // Output assembly name scriptCompileCounter++; - string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( - m_scriptEngine.World.RegionInfo.RegionID.ToString(), - FilePrefix + "_compiled_" + asset + ".dll")); try { - File.Delete(OutFile); + File.Delete(assembly); } catch (Exception e) // NOTLEGIT - Should be just FileIOException { @@ -492,7 +496,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools if (WriteScriptSourceToDebugFile) { string srcFileName = FilePrefix + "_source_" + - Path.GetFileNameWithoutExtension(OutFile) + ext; + Path.GetFileNameWithoutExtension(assembly) + ext; try { File.WriteAllText(Path.Combine(Path.Combine( @@ -528,7 +532,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } parameters.GenerateExecutable = false; - parameters.OutputAssembly = OutFile; + parameters.OutputAssembly = assembly; parameters.IncludeDebugInformation = CompileWithDebugInformation; //parameters.WarningLevel = 1; // Should be 4? parameters.TreatWarningsAsErrors = false; @@ -609,7 +613,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools if (severity == "Error") { - lslPos = FindErrorPosition(CompErr.Line, CompErr.Column); + lslPos = FindErrorPosition(CompErr.Line, CompErr.Column, m_lineMaps[assembly]); string text = CompErr.ErrorText; // Use LSL type names @@ -635,14 +639,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools // the compile may not be immediately apparent. Wait a // reasonable amount of time before giving up on it. - if (!File.Exists(OutFile)) + if (!File.Exists(assembly)) { - for (int i=0; i<20 && !File.Exists(OutFile); i++) + for (int i=0; i<20 && !File.Exists(assembly); i++) { System.Threading.Thread.Sleep(250); } // One final chance... - if (!File.Exists(OutFile)) + if (!File.Exists(assembly)) { errtext = String.Empty; errtext += "No compile error. But not able to locate compiled file."; @@ -658,7 +662,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools // // Read the binary file into a buffer // - FileInfo fi = new FileInfo(OutFile); + FileInfo fi = new FileInfo(assembly); if (fi == null) { @@ -671,7 +675,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools try { - FileStream fs = File.Open(OutFile, FileMode.Open, FileAccess.Read); + FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read); fs.Read(data, 0, data.Length); fs.Close(); } @@ -690,34 +694,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools Byte[] buf = enc.GetBytes(filetext); - FileStream sfs = File.Create(OutFile+".text"); + FileStream sfs = File.Create(assembly+".text"); sfs.Write(buf, 0, buf.Length); sfs.Close(); - string posmap = String.Empty; - if (m_positionMap != null) - { - foreach (KeyValuePair, KeyValuePair> kvp in m_positionMap) - { - KeyValuePair k = kvp.Key; - KeyValuePair v = kvp.Value; - posmap += String.Format("{0},{1},{2},{3}\n", - k.Key, k.Value, v.Key, v.Value); - } - } - - buf = enc.GetBytes(posmap); - - FileStream mfs = File.Create(OutFile+".map"); - mfs.Write(buf, 0, buf.Length); - mfs.Close(); - - return OutFile; - } - - public KeyValuePair FindErrorPosition(int line, int col) - { - return FindErrorPosition(line, col, m_positionMap); + return assembly; } private class kvpSorter : IComparer> @@ -791,27 +772,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools return message; } - public Dictionary, KeyValuePair> LineMap() + + private static void WriteMapFile(string filename, Dictionary, KeyValuePair> linemap) { - if (m_positionMap == null) - return null; - - Dictionary, KeyValuePair> ret = - new Dictionary, KeyValuePair>(); - - foreach (KeyValuePair kvp in m_positionMap.Keys) - ret.Add(kvp, m_positionMap[kvp]); - - return ret; + string mapstring = String.Empty; + foreach (KeyValuePair, KeyValuePair> kvp in linemap) + { + KeyValuePair k = kvp.Key; + KeyValuePair v = kvp.Value; + mapstring += String.Format("{0},{1},{2},{3}\n", k.Key, k.Value, v.Key, v.Value); + } + + System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + Byte[] mapbytes = enc.GetBytes(mapstring); + FileStream mfs = File.Create(filename); + mfs.Write(mapbytes, 0, mapbytes.Length); + mfs.Close(); } - private void ReadMapFile(string filename) + + private static Dictionary, KeyValuePair> ReadMapFile(string filename) { + Dictionary, KeyValuePair> linemap; try { StreamReader r = File.OpenText(filename); - - m_positionMap = new Dictionary, KeyValuePair>(); + linemap = new Dictionary, KeyValuePair>(); string line; while ((line = r.ReadLine()) != null) @@ -825,12 +811,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools KeyValuePair k = new KeyValuePair(kk, kv); KeyValuePair v = new KeyValuePair(vk, vv); - m_positionMap[k] = v; + linemap[k] = v; } } catch { + linemap = new Dictionary, KeyValuePair>(); } + return linemap; } } } -- cgit v1.1