Browse Source

ENH: add caching for the input CMakeList.txt files, 2X speed up

Bill Hoffman 24 years ago
parent
commit
5edd7673e1

+ 4 - 0
Source/CMakeLib.dsp

@@ -117,6 +117,10 @@ SOURCE=.\cmDSWWriter.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=.\cmListFileCache.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=.\cmMakeDepend.cxx
 # End Source File
 # Begin Source File

+ 1 - 0
Source/CMakeLists.txt

@@ -24,6 +24,7 @@ cmCustomCommand.cxx
 cmCacheManager.cxx
 cmCableClassSet.cxx
 cmSourceGroup.cxx
+cmListFileCache.cxx
 )
 
 # configure the .h file

+ 0 - 3
Source/CMakeSetup.dsw

@@ -32,9 +32,6 @@ Package=<4>
     Begin Project Dependency
     Project_Dep_Name ctest
     End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name DumpDocumentation
-    End Project Dependency
 }}}
 
 ###############################################################################

+ 1 - 0
Source/Makefile.in

@@ -29,6 +29,7 @@ cmTarget.o \
 cmCustomCommand.o \
 cmCacheManager.o \
 cmCableClassSet.o \
+cmListFileCache.o \
 cmSourceGroup.o
 
 DEPENDS = $(srcdir)/*.h  cmConfigure.h

+ 86 - 0
Source/cmListFileCache.cxx

@@ -0,0 +1,86 @@
+#include "cmListFileCache.h"
+#include "cmSystemTools.h"
+
+
+cmListFileCache* cmListFileCache::Instance = 0;
+
+
+cmListFileCache* cmListFileCache::GetInstance()
+{
+  if(!cmListFileCache::Instance)
+    {
+    cmListFileCache::Instance = new cmListFileCache;
+    }
+  return cmListFileCache::Instance;
+}
+
+
+void cmListFileCache::ClearCache()
+{
+  delete cmListFileCache::Instance;
+  cmListFileCache::Instance = 0;
+}
+
+
+
+cmListFile* cmListFileCache::GetFileCache(const char* path)
+{
+  ListFileMap::iterator sl = m_ListFileCache.find(path);
+  if (sl == m_ListFileCache.end())
+    {
+    // if not already in the map, then parse and store the 
+    // file
+    if(!this->CacheFile(path))
+      {
+      return 0;
+      }
+    sl = m_ListFileCache.find(path);
+    if (sl == m_ListFileCache.end())
+      {
+      cmSystemTools::Error("Fatal error, in cmListFileCache CacheFile failed",
+                           path);
+      return 0;
+      }
+    }
+  cmListFile& ret = sl->second;
+  if(cmSystemTools::ModifiedTime(path) > ret.m_ModifiedTime )
+    {
+    if(!this->CacheFile(path))
+      {
+      return 0;
+      }
+    else
+      {
+      sl = m_ListFileCache.find(path);
+      return &sl->second;
+      }
+    } 
+  return &ret;
+}
+
+
+bool cmListFileCache::CacheFile(const char* path)
+{
+  std::ifstream fin(path);
+  if(!fin)
+    {
+    cmSystemTools::Error("error can not open file ", path);
+    return false;
+    }
+  std::string name;
+  std::vector<std::string> arguments;
+  cmListFile inFile;
+  inFile.m_ModifiedTime = cmSystemTools::ModifiedTime(path);
+  while ( fin )
+    {
+    cmListFileFunction inFunction;
+    if(cmSystemTools::ParseFunction(fin, 
+                                    inFunction.m_Name,
+                                    inFunction.m_Arguments))
+      {
+      inFile.m_Functions.push_back(inFunction);
+      }
+    }
+  m_ListFileCache[path] = inFile;
+  return true;
+}

+ 88 - 0
Source/cmListFileCache.h

@@ -0,0 +1,88 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+   nor of any contributors, may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+  * Modified source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#ifndef cmListFileCache_h
+#define cmListFileCache_h
+
+#include "cmStandardIncludes.h"
+
+/** \class cmListFileCache
+ * \brief A class to cache list file contents.
+ *
+ * cmListFileCache is a class used to cache the contents of parsed
+ * cmake list files.
+ */
+
+struct cmListFileFunction
+{
+  std::string m_Name;
+  std::vector<std::string> m_Arguments;
+};
+
+struct cmListFile
+{
+  long int m_ModifiedTime;
+  std::vector<cmListFileFunction> m_Functions;
+};
+
+class cmListFileCache
+{
+public:
+  static cmListFileCache* GetInstance();
+  static void ClearCache();
+
+
+  /** Return the cached version of the given file.
+   *  If the file is not already in the cache, a cache entry
+   *  will be made.  If there is an error loading the file,
+   *  NULL is returned.
+   */
+  cmListFile* GetFileCache(const char* path);
+private:
+  // Cache the file
+  bool cmListFileCache::CacheFile(const char* path);
+  // private data
+  typedef std::map<cmStdString, cmListFile> ListFileMap;
+  ListFileMap m_ListFileCache;  // file name to ListFile map
+  static cmListFileCache* Instance; // singelton pointer
+};
+
+
+#endif

+ 14 - 10
Source/cmMakefile.cxx

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "cmCommands.h"
 #include "cmCacheManager.h"
 #include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
 #include <stdio.h>  // required for sprintf
 
 // default is not to be building executables
@@ -324,24 +325,27 @@ bool cmMakefile::ReadListFile(const char* filename, const char* external)
     {
     filenametoread= external;
     }
-  
-  std::ifstream fin(filenametoread);
-  if(!fin)
+
+  cmListFile* lf = 
+    cmListFileCache::GetInstance()->GetFileCache(filenametoread);
+  if(!lf)
     {
     cmSystemTools::Error("error can not open file ", filenametoread);
     return false;
     }
+  // add this list file to the list of dependencies
+  m_ListFiles.push_back( filenametoread);
   std::string name;
   std::vector<std::string> arguments;
-  while ( fin )
+  int numberFunctions = lf->m_Functions.size();
+  for(int i =0; i < numberFunctions; ++i)
     {
-    // add this list file to the list of dependencies
-    m_ListFiles.push_back( filenametoread);
-
-    if(cmSystemTools::ParseFunction(fin, name, arguments) &&
-       !this->IsFunctionBlocked(name.c_str(),arguments))
+    cmListFileFunction& curFunction = lf->m_Functions[i];
+    if(!this->IsFunctionBlocked(curFunction.m_Name.c_str(),
+                                curFunction.m_Arguments))
       {
-      this->ExecuteCommand(name,arguments);
+      this->ExecuteCommand(curFunction.m_Name,
+                           curFunction.m_Arguments);
       }
     }