[clang-tools-extra] r303321 - [clang-tidy] Optimize GlobList::contains

Alexander Kornienko via cfe-commits cfe-commits at lists.llvm.org
Wed May 17 18:13:51 PDT 2017


Author: alexfh
Date: Wed May 17 20:13:51 2017
New Revision: 303321

URL: http://llvm.org/viewvc/llvm-project?rev=303321&view=rev
Log:
[clang-tidy] Optimize GlobList::contains

With large lists of checks and large number of warnings GlobList::contains
starts being ridiculously CPU hungry, since it runs regexp match per glob.
Caching results of glob matching in a StringMap significantly speeds up check
filtering even for small GlobLists.

/tmp/q.cc:

void f() {
  int I;
  {int I;}
  {int I;}
  {int I;}
  ... // 200k times
}

Before the patch:

GlobList with 2 entries:
  $ time clang-tidy-old -checks=-*,modernize-use-override /tmp/q.cc -- -Wshadow
  200000 warnings generated.
  Suppressed 200000 warnings (200000 with check filters).

  real    0m3.826s
  user    0m3.176s
  sys     0m0.504s

GlobList with 28 entries:
  $ time clang-tidy-old -checks=-*,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,modernize-use-override /tmp/q.cc -- -Wshadow
  200000 warnings generated.
  Suppressed 200000 warnings (200000 with check filters).

  real    0m5.000s
  user    0m4.744s
  sys     0m0.060s

GlobList with 158 entries:
  $ time clang-tidy-old -checks=-*,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,modernize-use-override /tmp/q.cc -- -Wshadow
  200000 warnings generated.
  Suppressed 200000 warnings (200000 with check filters).

  real    0m13.920s
  user    0m13.636s
  sys     0m0.104s

With the patch runtime is practically independent from the length of the GlobList:
  $ time clang-tidy-new -checks=-*,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,modernize-use-override /tmp/q.cc -- -Wshadow
  200000 warnings generated.
  Suppressed 200000 warnings (200000 with check filters).

  real    0m2.300s
  user    0m2.104s
  sys     0m0.044s

Modified:
    clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp
    clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp?rev=303321&r1=303320&r2=303321&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp Wed May 17 20:13:51 2017
@@ -158,6 +158,26 @@ bool GlobList::contains(StringRef S, boo
   return Contains;
 }
 
+class ClangTidyContext::CachedGlobList {
+public:
+  CachedGlobList(StringRef Globs) : Globs(Globs) {}
+
+  bool contains(StringRef S) {
+    switch (auto &Result = Cache[S]) {
+      case Yes: return true;
+      case No: return false;
+      case None:
+        Result = Globs.contains(S) ? Yes : No;
+        return Result == Yes;
+    }
+  }
+
+private:
+  GlobList Globs;
+  enum Tristate { None, Yes, No };
+  llvm::StringMap<Tristate> Cache;
+};
+
 ClangTidyContext::ClangTidyContext(
     std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider)
     : DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),
@@ -167,6 +187,8 @@ ClangTidyContext::ClangTidyContext(
   setCurrentFile("");
 }
 
+ClangTidyContext::~ClangTidyContext() = default;
+
 DiagnosticBuilder ClangTidyContext::diag(
     StringRef CheckName, SourceLocation Loc, StringRef Description,
     DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
@@ -188,8 +210,9 @@ void ClangTidyContext::setSourceManager(
 void ClangTidyContext::setCurrentFile(StringRef File) {
   CurrentFile = File;
   CurrentOptions = getOptionsForFile(CurrentFile);
-  CheckFilter.reset(new GlobList(*getOptions().Checks));
-  WarningAsErrorFilter.reset(new GlobList(*getOptions().WarningsAsErrors));
+  CheckFilter = llvm::make_unique<CachedGlobList>(*getOptions().Checks);
+  WarningAsErrorFilter =
+      llvm::make_unique<CachedGlobList>(*getOptions().WarningsAsErrors);
 }
 
 void ClangTidyContext::setASTContext(ASTContext *Context) {
@@ -243,9 +266,9 @@ ClangTidyDiagnosticConsumer::ClangTidyDi
       LastErrorRelatesToUserCode(false), LastErrorPassesLineFilter(false),
       LastErrorWasIgnored(false) {
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
-  Diags.reset(new DiagnosticsEngine(
+  Diags = llvm::make_unique<DiagnosticsEngine>(
       IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,
-      /*ShouldOwnClient=*/false));
+      /*ShouldOwnClient=*/false);
   Context.setDiagnosticsEngine(Diags.get());
 }
 
@@ -461,8 +484,8 @@ void ClangTidyDiagnosticConsumer::checkF
 
 llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
   if (!HeaderFilter)
-    HeaderFilter.reset(
-        new llvm::Regex(*Context.getOptions().HeaderFilterRegex));
+    HeaderFilter =
+        llvm::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
   return HeaderFilter.get();
 }
 

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h?rev=303321&r1=303320&r2=303321&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h Wed May 17 20:13:51 2017
@@ -106,6 +106,8 @@ public:
   /// \brief Initializes \c ClangTidyContext instance.
   ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider);
 
+  ~ClangTidyContext();
+
   /// \brief Report any errors detected using this method.
   ///
   /// This is still under heavy development and will likely change towards using
@@ -202,8 +204,9 @@ private:
 
   std::string CurrentFile;
   ClangTidyOptions CurrentOptions;
-  std::unique_ptr<GlobList> CheckFilter;
-  std::unique_ptr<GlobList> WarningAsErrorFilter;
+  class CachedGlobList;
+  std::unique_ptr<CachedGlobList> CheckFilter;
+  std::unique_ptr<CachedGlobList> WarningAsErrorFilter;
 
   LangOptions LangOpts;
 




More information about the cfe-commits mailing list