Browse Source

Ninja: Cache ConvertToNinjaPath results to avoid repeat work

Calls to this method may dominate generation time in some cases.
Measurements for configuring cmake itself show a cache hit rate of ~57%
(7753 total calls, 4453 cache hits).  For a larger project (that also
makes use of custom targets as prerequisite for all compile targets),
the measured cache hit ratio is ~96% (2530827 total calls, 2433124 cache
hits).  For this project the observable cmake runtime could be reduced
from 40s to 30s.

Signed-off-by: Matthias Maennich <[email protected]>
Matthias Maennich 8 years ago
parent
commit
7374cb857c
2 changed files with 15 additions and 5 deletions
  1. 10 4
      Source/cmGlobalNinjaGenerator.cxx
  2. 5 1
      Source/cmGlobalNinjaGenerator.h

+ 10 - 4
Source/cmGlobalNinjaGenerator.cxx

@@ -861,18 +861,24 @@ static void EnsureTrailingSlash(std::string& path)
 #endif
 }
 
-std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(
+std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
   const std::string& path) const
 {
+  auto const f = ConvertToNinjaPathCache.find(path);
+  if (f != ConvertToNinjaPathCache.end()) {
+    return f->second;
+  }
+
   cmLocalNinjaGenerator* ng =
     static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
-  std::string convPath = ng->ConvertToRelativePath(
-    this->LocalGenerators[0]->GetState()->GetBinaryDirectory(), path);
+  const char* bin_dir = ng->GetState()->GetBinaryDirectory();
+  std::string convPath = ng->ConvertToRelativePath(bin_dir, path);
   convPath = this->NinjaOutputPath(convPath);
 #ifdef _WIN32
   std::replace(convPath.begin(), convPath.end(), '/', '\\');
 #endif
-  return convPath;
+  return ConvertToNinjaPathCache.emplace(path, std::move(convPath))
+    .first->second;
 }
 
 void cmGlobalNinjaGenerator::AddCXXCompileCommand(

+ 5 - 1
Source/cmGlobalNinjaGenerator.h

@@ -9,6 +9,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -245,7 +246,7 @@ public:
     return this->RulesFileStream;
   }
 
-  std::string ConvertToNinjaPath(const std::string& path) const;
+  std::string const& ConvertToNinjaPath(const std::string& path) const;
 
   struct MapToNinjaPathImpl
   {
@@ -452,6 +453,9 @@ private:
 
   std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures;
 
+  /// the local cache for calls to ConvertToNinjaPath
+  mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache;
+
   std::string NinjaCommand;
   std::string NinjaVersion;
   bool NinjaSupportsConsolePool;