So i was fooling around with the code and noticed that every time you run a script (even if it hasn't changed) your method PreProcessScript()
takes 3.7 seconds to run on my machine (and my machine is fast
).
What I have managed to do is .... before calling PreProcessScript() in the PythonScriptEngine.Start() Method
Code: Select all
1) I create i md5 hash of the unmodified script variable
2) and then check to see if there is a temp file in "[temp folder]/freepie/[scriptfile_withoutextension]_[hash].py"
a. on first run there isn't a temp file there,so it runs script = PreProcessScript()
b. I erase previous versions of the temp file with the same [scriptfile] prefix, so that the temp folder doesn't explode :)
c. Saves the modified script to a file named "[scriptfile_withoutextension]_[hash].py"
3) on subsequent runs the tempfile is there so it ReadsAllText from it into the script variable.
- loading this cached version, happens nearly instantly as it doesn't have to run PreProcessScript() if the file hasn't been modified
subsequent runs of an unmodified script drops from 3.7 seconds to .00000587 seconds
the code looks like this which is added to PythonScriptEngine.Start()
Code: Select all
string tempfolder = Path.Combine(Path.GetTempPath(),"freepie");
try
{
if (!Directory.Exists(tempfolder))
Directory.CreateDirectory(tempfolder);
string tempfile = Path.Combine(tempfolder, String.Format("{0}_{1}.py", Path.GetFileNameWithoutExtension(_scriptfile), GetHashString(script)));
Common.FileSystem fs = new FileSystem();
if (!File.Exists(tempfile))
{
script = PreProcessScript(script, usedGlobalEnums, globals);
//Delete old cached versions before writing the new one
string[] files = Directory.GetFiles(tempfolder,Path.GetFileNameWithoutExtension(_scriptfile)+"_*.py");
files.ToList().ForEach(f => File.Delete(f));
fs.WriteAllText(tempfile, script);
}
else
script = fs.ReadAllText(tempfile);
}
catch
{
tempfolder = "";
}
finally
{
if(String.IsNullOrEmpty(tempfolder))
script = PreProcessScript(script, usedGlobalEnums, globals);
}
md5 hashing uses this method i created
Code: Select all
string GetHashString(string str)
{
String md5Result;
StringBuilder sb = new StringBuilder();
MD5 md5Hasher = MD5.Create();
byte[] ba = Encoding.UTF8.GetBytes(str);
using (MemoryStream ms = new MemoryStream(ba))
{
foreach (Byte b in md5Hasher.ComputeHash(ms))
sb.Append(b.ToString("x2").ToLower());
}
md5Result = sb.ToString();
return md5Result;
}
Now i realize that you have a class called UacCompliantPaths under freepie core project, where you store the system paths used by FreePie.
I could have added it here, but as this was a quick fix, i didn't do it.
I couldn't find anywhere that you store general purpose static utility functions, so I wasn't sure where the best place to put the GetHashString() Method.
In order to get the file name of the original script i had to add one more method to the IScriptEngine Interface called void StartWithFile(string script);
in the implementation i store the filename into a private variable _scriptFile, read the text from the file , and call Start(script) with it
anyway what do you think?
is a good idea is it worth adding to the project?
would you like me to submit my modified Start Method for you to code review?
P.S. by the way it seems that VersionInfo.cs is missing from the github repo