MantisBT - CMake
View Issue Details
0015201CMakeCMakepublic2014-10-09 11:072015-05-04 09:05
Knuckles The Dog 
Ben Boeckel 
normalmajoralways
closedfixed 
Apple MacOS X 10.910.9
CMake 3.0.2 
CMake 3.2CMake 3.2 
0015201: Xcode generator is unusably slow on large projects
I am building a large project, over a thousand CMakeList.txt files resulting in hundreds of Xcode projects being generated. This takes at least 6 times longer than the same makefile generation.

I have profiled cmake 3.0.2 and found a significant bottleneck in cmGlobalXCodeGenerator::FindXCodeTarget() because the objects are stored in a vector and this vector has to be iterated over each time to find a target. This is done thousands of times in the course of generating the Xcode project.

As a quick fix I did the following:

cmGlobalXCodeGenerator.h, added member var:
std::unordered_map<const cmTarget*, cmXCodeObject*> mXcodeObjectMap;

cmGlobalXCodeGenerator.cpp
void cmGlobalXCodeGenerator::ClearXCodeObjects()
added to end of method: mXcodeObjectMap.clear();

cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
Under call to target->SetTarget(...) added: mXcodeObjectMap[&cmtarget] = target;

cmGlobalXCodeGenerator::CreateXCodeTarget(...)
Under call to target->SetTarget(...) added: mXcodeObjectMap[&cmtarget] = target;

cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget const* t)
rewrote to:
cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget const* t)
{
  if(!t)
    {
    return 0;
    }
  
  std::unordered_map<const cmTarget*, cmXCodeObject*>::iterator iter = mXcodeObjectMap.find(t);
  if (iter == mXcodeObjectMap.end())
  {
    return 0;
  }
  return iter->second;
}
So basically rather than constantly iterating through a vector for the Xcode object with the right target, it now keeps an unordered map where the key is the target pointer, and the object is the Xcode object. This reduces the lookup time enormously.

With only this change the generation of the project I'm working on goes down from well over an hour to around 10 mins, which puts it inline with the makefile generator performance.
Build a large set of projects.
No tags attached.
Issue History
2014-10-09 11:07Knuckles The DogNew Issue
2014-10-09 11:12Brad KingAssigned To => Ben Boeckel
2014-10-09 11:12Brad KingStatusnew => assigned
2014-10-09 11:12Brad KingTarget Version => CMake 3.2
2014-12-01 12:59Ben BoeckelNote Added: 0037337
2014-12-01 12:59Ben BoeckelStatusassigned => acknowledged
2014-12-02 11:17Brad KingNote Added: 0037358
2014-12-02 11:17Brad KingStatusacknowledged => resolved
2014-12-02 11:17Brad KingResolutionopen => fixed
2014-12-02 11:17Brad KingFixed in Version => CMake 3.2
2015-05-04 09:05Robert MaynardNote Added: 0038687
2015-05-04 09:05Robert MaynardStatusresolved => closed

Notes
(0037337)
Ben Boeckel   
2014-12-01 12:59   
I've made a patch and merged it to next which does a similar thing (it uses std::map instead). std::unordered_map is not available on all of CMake's targets and a pointer compare is pretty cheap (not as cheap as a hash on it, but better than std::string compares at least.
(0037358)
Brad King   
2014-12-02 11:17   
Re 0015201:0037337: After one fixup the patch is now a commit here:

 Xcode: use a map to look up target pointers
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=48f78f5f [^]
(0038687)
Robert Maynard   
2015-05-04 09:05   
Closing resolved issues that have not been updated in more than 4 months.