PERF: apply patch for bug 2575 speeds up depend scanning

This commit is contained in:
Bill Hoffman 2005-12-09 13:58:55 -05:00
parent 3a3ffea532
commit 92b6c8e742
3 changed files with 174 additions and 25 deletions

View File

@ -17,6 +17,7 @@
#include "cmDependsC.h"
#include "cmSystemTools.h"
#include "cmFileTimeComparison.h"
#include <ctype.h> // isspace
@ -30,18 +31,28 @@ cmDependsC::cmDependsC():
// yummy look at all those constructor arguments
cmDependsC::cmDependsC(std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex,
std::set<cmStdString> const& generatedFiles):
std::set<cmStdString> const& generatedFiles,
const cmStdString& cacheFileName):
m_IncludePath(&includes),
m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
m_IncludeRegexScan(scanRegex),
m_IncludeRegexComplain(complainRegex),
m_GeneratedFiles(&generatedFiles)
m_GeneratedFiles(&generatedFiles),
m_cacheFileName(cacheFileName)
{
this->ReadCacheFile();
}
//----------------------------------------------------------------------------
cmDependsC::~cmDependsC()
{
this->WriteCacheFile();
for (std::map<cmStdString, cmIncludeLines*>::iterator it=m_fileCache.begin();
it!=m_fileCache.end(); ++it)
{
delete it->second;
}
}
//----------------------------------------------------------------------------
@ -142,18 +153,38 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
// Record scanned files.
scanned.insert(fullName);
// Try to scan the file. Just leave it out if we cannot find
// it.
std::ifstream fin(fullName.c_str());
if(fin)
// Check whether this file is already in the cache
std::map<cmStdString, cmIncludeLines*>::iterator fileIt=m_fileCache.find(fullName);
if (fileIt!=m_fileCache.end())
{
// Add this file as a dependency.
fileIt->second->used=true;
dependencies.insert(fullName);
for (std::list<UnscannedEntry>::const_iterator incIt=
fileIt->second->list.begin(); incIt!=fileIt->second->list.end(); ++incIt)
{
if (m_Encountered.find(incIt->FileName) == m_Encountered.end())
{
m_Encountered.insert(incIt->FileName);
m_Unscanned.push(*incIt);
}
}
}
else
{
// Scan this file for new dependencies. Pass the directory
// containing the file to handle double-quote includes.
std::string dir = cmSystemTools::GetFilenamePath(fullName);
this->Scan(fin, dir.c_str());
// Try to scan the file. Just leave it out if we cannot find
// it.
std::ifstream fin(fullName.c_str());
if(fin)
{
// Add this file as a dependency.
dependencies.insert(fullName);
// Scan this file for new dependencies. Pass the directory
// containing the file to handle double-quote includes.
std::string dir = cmSystemTools::GetFilenamePath(fullName);
this->Scan(fin, dir.c_str(), fullName);
}
}
}
@ -166,8 +197,8 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
i != dependencies.end(); ++i)
{
makeDepends << obj << ": "
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
<< std::endl;
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
<< std::endl;
internalDepends << " " << i->c_str() << std::endl;
}
makeDepends << std::endl;
@ -176,8 +207,105 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
}
//----------------------------------------------------------------------------
void cmDependsC::Scan(std::istream& is, const char* directory)
void cmDependsC::ReadCacheFile()
{
if(m_cacheFileName.size() == 0)
{
return;
}
std::ifstream fin(m_cacheFileName.c_str());
if(!fin)
{
return;
}
std::string line;
cmIncludeLines* cacheEntry=0;
bool haveFileName=false;
while(cmSystemTools::GetLineFromStream(fin, line))
{
if (line.empty())
{
cacheEntry=0;
haveFileName=false;
continue;
}
//the first line after an empty line is the name of the parsed file
if (haveFileName==false)
{
haveFileName=true;
int newer=0;
cmFileTimeComparison comp;
bool res=comp.FileTimeCompare(m_cacheFileName.c_str(), line.c_str(), &newer);
if ((res==true) && (newer==1)) //cache is newer than the parsed file
{
cacheEntry=new cmIncludeLines;
m_fileCache[line]=cacheEntry;
}
}
else if (cacheEntry!=0)
{
UnscannedEntry entry;
entry.FileName = line;
if (cmSystemTools::GetLineFromStream(fin, line))
{
if (line!="-")
{
entry.QuotedLocation=line;
}
cacheEntry->list.push_back(entry);
}
}
}
}
//----------------------------------------------------------------------------
void cmDependsC::WriteCacheFile() const
{
if(m_cacheFileName.size() == 0)
{
return;
}
std::ofstream cacheOut(m_cacheFileName.c_str());
if(!cacheOut)
{
return;
}
for (std::map<cmStdString, cmIncludeLines*>::const_iterator fileIt=m_fileCache.begin();
fileIt!=m_fileCache.end(); ++fileIt)
{
if (fileIt->second->used)
{
cacheOut<<fileIt->first.c_str()<<std::endl;
for (std::list<UnscannedEntry>::const_iterator incIt=fileIt->second->list.begin();
incIt!=fileIt->second->list.end(); ++incIt)
{
cacheOut<<incIt->FileName.c_str()<<std::endl;
if (incIt->QuotedLocation.empty())
{
cacheOut<<"-"<<std::endl;
}
else
{
cacheOut<<incIt->QuotedLocation.c_str()<<std::endl;
}
}
cacheOut<<std::endl;
}
}
}
//----------------------------------------------------------------------------
void cmDependsC::Scan(std::istream& is, const char* directory, const cmStdString& fullName)
{
cmIncludeLines* newCacheEntry=new cmIncludeLines;
newCacheEntry->used=true;
m_fileCache[fullName]=newCacheEntry;
// Read one line at a time.
std::string line;
while(cmSystemTools::GetLineFromStream(is, line))
@ -204,11 +332,14 @@ void cmDependsC::Scan(std::istream& is, const char* directory)
// is included by double-quotes and the other by angle brackets.
// This kind of problem will be fixed when a more
// preprocessor-like implementation of this scanner is created.
if(m_Encountered.find(entry.FileName) == m_Encountered.end() &&
m_IncludeRegexScan.find(entry.FileName.c_str()))
if (m_IncludeRegexScan.find(entry.FileName.c_str()))
{
m_Encountered.insert(entry.FileName);
m_Unscanned.push(entry);
newCacheEntry->list.push_back(entry);
if(m_Encountered.find(entry.FileName) == m_Encountered.end())
{
m_Encountered.insert(entry.FileName);
m_Unscanned.push(entry);
}
}
}
}

View File

@ -32,7 +32,7 @@ public:
cmDependsC();
cmDependsC(std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex,
std::set<cmStdString> const& generatedFiles);
std::set<cmStdString> const& generatedFiles, const cmStdString& cachFileName);
/** Virtual destructor to cleanup subclasses properly. */
virtual ~cmDependsC();
@ -47,7 +47,7 @@ protected:
std::ostream& internalDepends);
// Method to scan a single file.
void Scan(std::istream& is, const char* directory);
void Scan(std::istream& is, const char* directory, const cmStdString& fullName);
// Method to test for the existence of a file.
bool FileExistsOrIsGenerated(const std::string& fname,
@ -74,10 +74,24 @@ protected:
cmStdString FileName;
cmStdString QuotedLocation;
};
struct cmIncludeLines
{
cmIncludeLines():used(false) {}
std::list<UnscannedEntry> list;
bool used;
};
std::set<cmStdString> m_Encountered;
std::queue<UnscannedEntry> m_Unscanned;
t_CharBuffer m_Buffer;
std::map<cmStdString, cmIncludeLines *> m_fileCache;
cmStdString m_cacheFileName;
void WriteCacheFile() const;
void ReadCacheFile();
private:
cmDependsC(cmDependsC const&); // Purposely not implemented.
void operator=(cmDependsC const&); // Purposely not implemented.

View File

@ -2790,11 +2790,15 @@ cmLocalUnixMakefileGenerator3
cmDepends *scanner = 0;
if(lang == "C" || lang == "CXX" || lang == "RC")
{
std::string includeCacheFileName = dir;
includeCacheFileName += "/includecache.";
includeCacheFileName += lang;
// TODO: Handle RC (resource files) dependencies correctly.
scanner = new cmDependsC(includes,
includeRegexScan.c_str(),
includeRegexComplain.c_str(),
generatedFiles);
generatedFiles, includeCacheFileName);
}
#ifdef CMAKE_BUILD_WITH_CMAKE
else if(lang == "Fortran")