]> granicus.if.org Git - clang/commitdiff
Preallocate ExplodedNode hash table
authorBen Craig <ben.craig@codeaurora.org>
Fri, 10 Jun 2016 13:22:13 +0000 (13:22 +0000)
committerBen Craig <ben.craig@codeaurora.org>
Fri, 10 Jun 2016 13:22:13 +0000 (13:22 +0000)
Rehashing the ExplodedNode table is very expensive. The hashing
itself is expensive, and the general activity of iterating over the
hash table is highly cache unfriendly. Instead, we guess at the
eventual size by using the maximum number of steps allowed. This
generally avoids a rehash. It is possible that we still need to
rehash if the backlog of work that is added to the worklist
significantly exceeds the number of work items that we process. Even
if we do need to rehash in that scenario, this change is still a
win, as we still have fewer rehashes that we would have prior to
this change.

For small work loads, this will increase the memory used. For large
work loads, it will somewhat reduce the memory used. Speed is
significantly increased. A large .C file took 3m53.812s to analyze
prior to this change. Now it takes 3m38.976s, for a ~6% improvement.

http://reviews.llvm.org/D20933

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@272394 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
lib/StaticAnalyzer/Core/CoreEngine.cpp

index a4e922661685d9882c0bec58458014e2c83ea3d4..b14a1cc5f62fa418f8ca3c478c5378f8abc62937 100644 (file)
@@ -321,6 +321,8 @@ public:
   bool empty() const { return NumNodes == 0; }
   unsigned size() const { return NumNodes; }
 
+  void reserve(unsigned NodeCount) { Nodes.reserve(NodeCount); }
+
   // Iterators.
   typedef ExplodedNode                        NodeTy;
   typedef llvm::FoldingSet<ExplodedNode>      AllNodesTy;
index c75fb2e763db2e2429fc3507cbecee1285feaab6..da608f6c755883eb2394a6775cd14066b3643280 100644 (file)
@@ -208,6 +208,11 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
 
   // Check if we have a steps limit
   bool UnlimitedSteps = Steps == 0;
+  // Cap our pre-reservation in the event that the user specifies
+  // a very large number of maximum steps.
+  const unsigned PreReservationCap = 4000000;
+  if(!UnlimitedSteps)
+    G.reserve(std::min(Steps,PreReservationCap));
 
   while (WList->hasWork()) {
     if (!UnlimitedSteps) {