diff options
author | Marius Ungureanu <therzok@gmail.com> | 2018-03-28 18:25:47 +0300 |
---|---|---|
committer | Marius Ungureanu <teromario@yahoo.com> | 2018-04-17 14:13:26 +0300 |
commit | 06dc79bb42e6c5d55dc73e9786b36ad7353f333c (patch) | |
tree | 1bd427520babebaa11922f7bb966634a8acc728d /main/src/core | |
parent | d2f7eef570898e21b901b68898fa8c656fe4c40b (diff) |
[Core] Reduce lock contention on imported files
This reduces lock contention on imported files by not locking on the
global project info dictionary when accessing it, instead locking on
each project info.
This should help with concurrent imports of different imported files
Diffstat (limited to 'main/src/core')
-rw-r--r-- | main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs index 5ead0ee69e..0e1ac4c2ad 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs @@ -47,6 +47,8 @@ namespace MonoDevelop.Projects.MSBuild public MSBuildProject Project; public DateTime LastWriteTime; public int ReferenceCount = 1; + public bool NeedsLoad = false; + public object LockObject = new object (); } class ProjectInfo @@ -130,38 +132,53 @@ namespace MonoDevelop.Projects.MSBuild MSBuildProject LoadProject (MSBuildEvaluationContext context, FilePath fileName) { fileName = fileName.CanonicalPath; + + LoadedProjectInfo pi; lock (loadedProjects) { - LoadedProjectInfo pi; - if (loadedProjects.TryGetValue (fileName, out pi)) { - pi.ReferenceCount++; - var lastWriteTime = File.GetLastWriteTime (fileName); - if (pi.LastWriteTime != lastWriteTime) { - pi.LastWriteTime = lastWriteTime; - pi.Project.Load (fileName, new MSBuildXmlReader { ForEvaluation = true }); - } - return pi.Project; + if (!loadedProjects.TryGetValue (fileName, out pi)) { + loadedProjects [fileName] = pi = new LoadedProjectInfo (); } - LogBeginProjectFileLoad (context, fileName); - MSBuildProject p = new MSBuildProject (EngineManager); - p.Load (fileName, new MSBuildXmlReader { ForEvaluation = true }); - loadedProjects [fileName] = new LoadedProjectInfo { Project = p, LastWriteTime = File.GetLastWriteTime (fileName) }; - LogEndProjectFileLoad (context); - return p; + pi.ReferenceCount++; + } + + lock (pi.LockObject) { + if (pi.Project == null) { + pi.Project = new MSBuildProject (EngineManager); + pi.NeedsLoad = true; + } + } + + lock (pi.LockObject) { + if (!pi.NeedsLoad) + pi.NeedsLoad = pi.LastWriteTime != File.GetLastWriteTimeUtc (fileName); + + if (pi.NeedsLoad) { + LogBeginProjectFileLoad (context, fileName); + pi.Project.Load (fileName, new MSBuildXmlReader { ForEvaluation = true }); + pi.NeedsLoad = false; + pi.LastWriteTime = File.GetLastWriteTimeUtc (fileName); + LogEndProjectFileLoad (context); + } + + return pi.Project; } } void UnloadProject (MSBuildProject project) { var fileName = project.FileName.CanonicalPath; + LoadedProjectInfo pi; lock (loadedProjects) { - LoadedProjectInfo pi; - if (loadedProjects.TryGetValue (fileName, out pi)) { - pi.ReferenceCount--; - if (pi.ReferenceCount == 0) { - loadedProjects.Remove (fileName); - project.Dispose (); - //Console.WriteLine ("Unloaded: " + fileName); - } + if (!loadedProjects.TryGetValue (fileName, out pi)) + return; + + pi.ReferenceCount--; + if (pi.ReferenceCount == 0) { + loadedProjects.Remove (fileName); + lock (pi.LockObject) + pi.Project = null; + project.Dispose (); + //Console.WriteLine ("Unloaded: " + fileName); } } } |