NREL/OpenStudio — pull request #806 by mbadams5 (2014-01-17 20:54:26+00:00)
Title: Speed Optimizations abound (~2 times speed up overall)

The results of these optimizations are as follows for some of the major hotspots, but not all:

1161ms -> 316msn (73%) istringEqual()
2037ms -> 746ms (63%) Workspace_Impl::nextName()
4354ms -> 1054ms (76%) WorkspaceObject_Impl::uniquelyIdentifiableByName()
1021ms -> 483ms (53%) Workspace_Impl::getObjectsByTypeAndName()
1267ms -> 271ms (79%) WorkspaceObject_Impl::SetName()
927ms -> 183ms (80%) Workspace_Impl::constructNextName()
3101ms -> 1350ms (56%) PlantLoop_Impl::addDemandBranchForComponent()
3792ms -> 1518ms (60%) AirLoopHVAC_Impl::addBranchForZone()
1940ms -> 1263ms (35%) ForwardTranslator::translateModel()
3231ms -> 1168ms (64%) Workspace_Impl::addObjects()
839ms -> 299ms (64%) IdfObject_Impl::name()

A bulk of the savings come from a few major changes to the underlying implementation of Workspace and WorkspaceObject.

istringEqual: changes from using boost::iequal to size and std::equal with a case insensitive char comparison. The downside to this new approach is that it can not handle localization, however, if needed it can be added in using std::locale. I did not think this was necessary at this point since there is no other precedence in OpenStudio for localization. This is part of the speed up i'm sure.

getObjectsByTypeAndName: m_iddObjectTypeMap now uses std::map> (WorkspaceObjectMap) instead of std::set as the second value in IddObjectTypeMap. Before, the implementation found a vector based on IddObjectType then called getObject(handle) on each object. The problem is that getObject(handle) searches ALL handles until it is found, meaning the more handles the longer it takes. By using WorkspaceObjectMap, now it searches only the subset of handles contained within the specific IddObjectType map, reducing search time dramatically.

uniquelyIdentifiableByName: The big change here is using getObjectsByType instead of getObjectsByReference. With the changes to m_iddObjectTypeMap, getObjectsByType is much faster lookup than getObjectsByReference. Even though this now uses IddObjectType instead of Reference to search for unique names, it should still be equivalent since names must be unique per IddObjectType in E+.

constructNextName: The big changes here are getBaseName, getNameSuffix (new), baseNamesMatch (new). These used to be regexes which were slow and called many times. Now it uses std lib functions find_last_of(), substr(), and char comparison. For what these regexes were looking for they were overkill, which is just a space followed by integer numbers. This can be done with std lib in much less time. These three functions are called many times throughout Workspace so the savings is huge not just for constructNextName. Also within constructNextName instead of using a set it now uses vector which is then sorted and non-unique entries erased. This is functionally similar to set but runs much faster due to how expensive set is to allocate, deallocate, and insert.

addBranchForZone (and addDemandBranchForComponent): These both benefit from the faster naming of new objects. I also changed how Loop::component, demandComponent, and supplyComponent work. They all return immediately after matching the handle of the object instead of gathering ALL objects then matching handles. For addBranchForZone specifically, it speeds up due to the elimination of an unnecessary call to remove() if an Air Terminal is passed into the function.

This passes all unit tests that the current develop branch passes as well. But obviously I would like some review on this since there are some changes to the base classes of all ModelObjects and also code coverage might not be 100%.

@kbenne @macumber @axelstudios @lefticus