[clang-tools-extra] [clang-query] add basic profiling on matching each ASTs (PR #114806)

Ding Fei via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 4 20:17:03 PST 2024


https://github.com/danix800 updated https://github.com/llvm/llvm-project/pull/114806

>From dfd42c06d94f859ec78ec1e5c3386c0e4016386f Mon Sep 17 00:00:00 2001
From: dingfei <fding at feysh.com>
Date: Mon, 4 Nov 2024 22:37:51 +0800
Subject: [PATCH 1/4] [clang-query] add basic profiling on matching each ASTs

Sample output:

$ cat test.cql
set enable-profile true
m binaryOperator(isExpansionInMainFile())

$ cat test.c
int test(int i, int j) {
  return i + j;
}

$ clang-query --track-memory -f test.cql test.c --

Match #1:

{{.*}}/test.c:2:10: note: "root" binds here
    2 |   return i + j;
      |          ^~~~~
1 match.
===-------------------------------------------------------------------------===
                         clang-query matcher profiling
===-------------------------------------------------------------------------===
  Total Execution Time: 0.0000 seconds (0.0000 wall clock)

   ---User Time---   --System Time--   --User+System--   ---Wall Time---  ---Mem---  --- Name ---
   0.0000 (100.0%)   0.0000 (100.0%)   0.0000 (100.0%)   0.0000 (100.0%)        224  {{.*}}/test.c
   0.0000 (100.0%)   0.0000 (100.0%)   0.0000 (100.0%)   0.0000 (100.0%)        224  Total
---
 clang-tools-extra/clang-query/CMakeLists.txt  |  1 +
 clang-tools-extra/clang-query/Query.cpp       | 26 ++++++++++++--
 clang-tools-extra/clang-query/QueryParser.cpp |  5 +++
 .../clang-query/QueryProfile.cpp              | 24 +++++++++++++
 clang-tools-extra/clang-query/QueryProfile.h  | 35 +++++++++++++++++++
 clang-tools-extra/clang-query/QuerySession.h  |  3 +-
 6 files changed, 90 insertions(+), 4 deletions(-)
 create mode 100644 clang-tools-extra/clang-query/QueryProfile.cpp
 create mode 100644 clang-tools-extra/clang-query/QueryProfile.h

diff --git a/clang-tools-extra/clang-query/CMakeLists.txt b/clang-tools-extra/clang-query/CMakeLists.txt
index b168a3a8581567..84a1ad6fa33582 100644
--- a/clang-tools-extra/clang-query/CMakeLists.txt
+++ b/clang-tools-extra/clang-query/CMakeLists.txt
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
 add_clang_library(clangQuery STATIC
   Query.cpp
   QueryParser.cpp
+  QueryProfile.cpp
 
   DEPENDS
   omp_gen
diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp
index 282d136aff721a..5b628de3c4deeb 100644
--- a/clang-tools-extra/clang-query/Query.cpp
+++ b/clang-tools-extra/clang-query/Query.cpp
@@ -8,6 +8,7 @@
 
 #include "Query.h"
 #include "QueryParser.h"
+#include "QueryProfile.h"
 #include "QuerySession.h"
 #include "clang/AST/ASTDumper.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -44,6 +45,8 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
         "  set bind-root (true|false)        "
         "Set whether to bind the root matcher to \"root\".\n"
         "  set print-matcher (true|false)    "
+        "  set enable-profile (true|false)    "
+        "Set whether to enable matcher profiling,\n"
         "Set whether to print the current matcher,\n"
         "  set traversal <kind>              "
         "Set traversal kind of clang-query session. Available kinds are:\n"
@@ -82,10 +85,13 @@ namespace {
 
 struct CollectBoundNodes : MatchFinder::MatchCallback {
   std::vector<BoundNodes> &Bindings;
-  CollectBoundNodes(std::vector<BoundNodes> &Bindings) : Bindings(Bindings) {}
+  StringRef Unit;
+  CollectBoundNodes(std::vector<BoundNodes> &Bindings, StringRef Unit)
+      : Bindings(Bindings), Unit(Unit) {}
   void run(const MatchFinder::MatchResult &Result) override {
     Bindings.push_back(Result.Nodes);
   }
+  StringRef getID() const override { return Unit; }
 };
 
 } // namespace
@@ -93,8 +99,19 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
 bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
   unsigned MatchCount = 0;
 
+  std::optional<QueryProfile> Profiling;
+  if (QS.EnableProfile)
+    Profiling = QueryProfile();
+
   for (auto &AST : QS.ASTs) {
-    MatchFinder Finder;
+    ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
+    std::optional<llvm::StringMap<llvm::TimeRecord>> Records;
+    if (QS.EnableProfile) {
+      Records.emplace();
+      FinderOptions.CheckProfiling.emplace(*Records);
+    }
+
+    MatchFinder Finder(FinderOptions);
     std::vector<BoundNodes> Matches;
     DynTypedMatcher MaybeBoundMatcher = Matcher;
     if (QS.BindRoot) {
@@ -102,7 +119,8 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
       if (M)
         MaybeBoundMatcher = *M;
     }
-    CollectBoundNodes Collect(Matches);
+    StringRef OrigSrcName = AST->getOriginalSourceFileName();
+    CollectBoundNodes Collect(Matches, OrigSrcName);
     if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) {
       OS << "Not a valid top-level matcher.\n";
       return false;
@@ -111,6 +129,8 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
     ASTContext &Ctx = AST->getASTContext();
     Ctx.getParentMapContext().setTraversalKind(QS.TK);
     Finder.matchAST(Ctx);
+    if (QS.EnableProfile)
+      Profiling->Records[OrigSrcName] += (*Records)[OrigSrcName];
 
     if (QS.PrintMatcher) {
       SmallVector<StringRef, 4> Lines;
diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp
index 97cb264a611af3..1d5ec281defd40 100644
--- a/clang-tools-extra/clang-query/QueryParser.cpp
+++ b/clang-tools-extra/clang-query/QueryParser.cpp
@@ -182,6 +182,7 @@ enum ParsedQueryVariable {
   PQV_Output,
   PQV_BindRoot,
   PQV_PrintMatcher,
+  PQV_EnableProfile,
   PQV_Traversal
 };
 
@@ -285,6 +286,7 @@ QueryRef QueryParser::doParse() {
             .Case("output", PQV_Output)
             .Case("bind-root", PQV_BindRoot)
             .Case("print-matcher", PQV_PrintMatcher)
+            .Case("enable-profile", PQV_EnableProfile)
             .Case("traversal", PQV_Traversal)
             .Default(PQV_Invalid);
     if (VarStr.empty())
@@ -303,6 +305,9 @@ QueryRef QueryParser::doParse() {
     case PQV_PrintMatcher:
       Q = parseSetBool(&QuerySession::PrintMatcher);
       break;
+    case PQV_EnableProfile:
+      Q = parseSetBool(&QuerySession::EnableProfile);
+      break;
     case PQV_Traversal:
       Q = parseSetTraversalKind(&QuerySession::TK);
       break;
diff --git a/clang-tools-extra/clang-query/QueryProfile.cpp b/clang-tools-extra/clang-query/QueryProfile.cpp
new file mode 100644
index 00000000000000..9b60f0bf1c7f4e
--- /dev/null
+++ b/clang-tools-extra/clang-query/QueryProfile.cpp
@@ -0,0 +1,24 @@
+//===-------- QueryProfile.cpp - clang-query --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "QueryProfile.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang::query {
+
+void QueryProfile::printUserFriendlyTable(llvm::raw_ostream &OS) {
+  TG->print(OS);
+  OS.flush();
+}
+
+QueryProfile::~QueryProfiling() {
+  TG.emplace("clang-query", "clang-query matcher profiling", Records);
+  printUserFriendlyTable(llvm::errs());
+}
+
+} // namespace clang::query
diff --git a/clang-tools-extra/clang-query/QueryProfile.h b/clang-tools-extra/clang-query/QueryProfile.h
new file mode 100644
index 00000000000000..6815dc0245bdc8
--- /dev/null
+++ b/clang-tools-extra/clang-query/QueryProfile.h
@@ -0,0 +1,35 @@
+//===--------- QueryProfile.h - clang-query ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PROFILE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PROFILE_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Timer.h"
+#include <optional>
+
+namespace llvm {
+class raw_ostream;
+} // namespace llvm
+
+namespace clang::query {
+
+class QueryProfile {
+public:
+  llvm::StringMap<llvm::TimeRecord> Records;
+  QueryProfile() = default;
+  ~QueryProfile();
+
+private:
+  std::optional<llvm::TimerGroup> TG;
+  void printUserFriendlyTable(llvm::raw_ostream &OS);
+};
+
+} // namespace clang::query
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PROFILE_H
diff --git a/clang-tools-extra/clang-query/QuerySession.h b/clang-tools-extra/clang-query/QuerySession.h
index 31a4900e26190b..c7d5a64c332008 100644
--- a/clang-tools-extra/clang-query/QuerySession.h
+++ b/clang-tools-extra/clang-query/QuerySession.h
@@ -26,7 +26,7 @@ class QuerySession {
   QuerySession(llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs)
       : ASTs(ASTs), PrintOutput(false), DiagOutput(true),
         DetailedASTOutput(false), BindRoot(true), PrintMatcher(false),
-        Terminate(false), TK(TK_AsIs) {}
+        EnableProfile(false), Terminate(false), TK(TK_AsIs) {}
 
   llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs;
 
@@ -36,6 +36,7 @@ class QuerySession {
 
   bool BindRoot;
   bool PrintMatcher;
+  bool EnableProfile;
   bool Terminate;
 
   TraversalKind TK;

>From ccd96f04747ff6809a15df07ddb58d6c378c21fb Mon Sep 17 00:00:00 2001
From: dingfei <fding at feysh.com>
Date: Mon, 4 Nov 2024 22:50:16 +0800
Subject: [PATCH 2/4] fix typos

---
 clang-tools-extra/clang-query/Query.cpp        | 6 +++---
 clang-tools-extra/clang-query/QueryProfile.cpp | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp
index 5b628de3c4deeb..9d5a6a32be7bbf 100644
--- a/clang-tools-extra/clang-query/Query.cpp
+++ b/clang-tools-extra/clang-query/Query.cpp
@@ -45,9 +45,9 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
         "  set bind-root (true|false)        "
         "Set whether to bind the root matcher to \"root\".\n"
         "  set print-matcher (true|false)    "
-        "  set enable-profile (true|false)    "
-        "Set whether to enable matcher profiling,\n"
         "Set whether to print the current matcher,\n"
+        "  set enable-profile (true|false)   "
+        "Set whether to enable matcher profiling,\n"
         "  set traversal <kind>              "
         "Set traversal kind of clang-query session. Available kinds are:\n"
         "    AsIs                            "
@@ -101,7 +101,7 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
 
   std::optional<QueryProfile> Profiling;
   if (QS.EnableProfile)
-    Profiling = QueryProfile();
+    Profiling.emplace();
 
   for (auto &AST : QS.ASTs) {
     ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
diff --git a/clang-tools-extra/clang-query/QueryProfile.cpp b/clang-tools-extra/clang-query/QueryProfile.cpp
index 9b60f0bf1c7f4e..aa24e0400dff3c 100644
--- a/clang-tools-extra/clang-query/QueryProfile.cpp
+++ b/clang-tools-extra/clang-query/QueryProfile.cpp
@@ -16,7 +16,7 @@ void QueryProfile::printUserFriendlyTable(llvm::raw_ostream &OS) {
   OS.flush();
 }
 
-QueryProfile::~QueryProfiling() {
+QueryProfile::~QueryProfile() {
   TG.emplace("clang-query", "clang-query matcher profiling", Records);
   printUserFriendlyTable(llvm::errs());
 }

>From 57151c6bec9d8d4c264d865f914f4de73987d4a7 Mon Sep 17 00:00:00 2001
From: dingfei <fding at feysh.com>
Date: Mon, 4 Nov 2024 23:05:47 +0800
Subject: [PATCH 3/4] fix punctuation error in command help text

---
 clang-tools-extra/clang-query/Query.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp
index 9d5a6a32be7bbf..74530937ac04a7 100644
--- a/clang-tools-extra/clang-query/Query.cpp
+++ b/clang-tools-extra/clang-query/Query.cpp
@@ -45,9 +45,9 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
         "  set bind-root (true|false)        "
         "Set whether to bind the root matcher to \"root\".\n"
         "  set print-matcher (true|false)    "
-        "Set whether to print the current matcher,\n"
+        "Set whether to print the current matcher.\n"
         "  set enable-profile (true|false)   "
-        "Set whether to enable matcher profiling,\n"
+        "Set whether to enable matcher profiling.\n"
         "  set traversal <kind>              "
         "Set traversal kind of clang-query session. Available kinds are:\n"
         "    AsIs                            "

>From 6b931b85222204b2acdfeaba1e406c8cd58d8d95 Mon Sep 17 00:00:00 2001
From: dingfei <fding at feysh.com>
Date: Tue, 5 Nov 2024 12:14:38 +0800
Subject: [PATCH 4/4] move QueryProfiler into Query.cpp

1. QueryProfiler is very small, no need to expose it;
2. TimerGroup is created when dumping profiling info,
   no need to be an optional member of QueryProfiler.
---
 clang-tools-extra/clang-query/CMakeLists.txt  |  1 -
 clang-tools-extra/clang-query/Query.cpp       | 28 ++++++++++++---
 .../clang-query/QueryProfile.cpp              | 24 -------------
 clang-tools-extra/clang-query/QueryProfile.h  | 35 -------------------
 4 files changed, 24 insertions(+), 64 deletions(-)
 delete mode 100644 clang-tools-extra/clang-query/QueryProfile.cpp
 delete mode 100644 clang-tools-extra/clang-query/QueryProfile.h

diff --git a/clang-tools-extra/clang-query/CMakeLists.txt b/clang-tools-extra/clang-query/CMakeLists.txt
index 84a1ad6fa33582..b168a3a8581567 100644
--- a/clang-tools-extra/clang-query/CMakeLists.txt
+++ b/clang-tools-extra/clang-query/CMakeLists.txt
@@ -7,7 +7,6 @@ set(LLVM_LINK_COMPONENTS
 add_clang_library(clangQuery STATIC
   Query.cpp
   QueryParser.cpp
-  QueryProfile.cpp
 
   DEPENDS
   omp_gen
diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp
index 74530937ac04a7..7db11e29661eca 100644
--- a/clang-tools-extra/clang-query/Query.cpp
+++ b/clang-tools-extra/clang-query/Query.cpp
@@ -8,7 +8,6 @@
 
 #include "Query.h"
 #include "QueryParser.h"
-#include "QueryProfile.h"
 #include "QuerySession.h"
 #include "clang/AST/ASTDumper.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -94,14 +93,35 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
   StringRef getID() const override { return Unit; }
 };
 
+class QueryProfiler {
+public:
+  QueryProfiler() = default;
+  ~QueryProfiler() { printUserFriendlyTable(llvm::errs()); }
+
+  void addASTUnitRecord(llvm::StringRef Unit, const llvm::TimeRecord &Record) {
+    Records[Unit] += Record;
+  }
+
+private:
+  void printUserFriendlyTable(llvm::raw_ostream &OS) {
+    llvm::TimerGroup TG("clang-query", "clang-query matcher profiling",
+                        Records);
+    TG.print(OS);
+    OS.flush();
+  }
+
+private:
+  llvm::StringMap<llvm::TimeRecord> Records;
+};
+
 } // namespace
 
 bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
   unsigned MatchCount = 0;
 
-  std::optional<QueryProfile> Profiling;
+  std::optional<QueryProfiler> Profiler;
   if (QS.EnableProfile)
-    Profiling.emplace();
+    Profiler.emplace();
 
   for (auto &AST : QS.ASTs) {
     ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
@@ -130,7 +150,7 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
     Ctx.getParentMapContext().setTraversalKind(QS.TK);
     Finder.matchAST(Ctx);
     if (QS.EnableProfile)
-      Profiling->Records[OrigSrcName] += (*Records)[OrigSrcName];
+      Profiler->addASTUnitRecord(OrigSrcName, (*Records)[OrigSrcName]);
 
     if (QS.PrintMatcher) {
       SmallVector<StringRef, 4> Lines;
diff --git a/clang-tools-extra/clang-query/QueryProfile.cpp b/clang-tools-extra/clang-query/QueryProfile.cpp
deleted file mode 100644
index aa24e0400dff3c..00000000000000
--- a/clang-tools-extra/clang-query/QueryProfile.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===-------- QueryProfile.cpp - clang-query --------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "QueryProfile.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang::query {
-
-void QueryProfile::printUserFriendlyTable(llvm::raw_ostream &OS) {
-  TG->print(OS);
-  OS.flush();
-}
-
-QueryProfile::~QueryProfile() {
-  TG.emplace("clang-query", "clang-query matcher profiling", Records);
-  printUserFriendlyTable(llvm::errs());
-}
-
-} // namespace clang::query
diff --git a/clang-tools-extra/clang-query/QueryProfile.h b/clang-tools-extra/clang-query/QueryProfile.h
deleted file mode 100644
index 6815dc0245bdc8..00000000000000
--- a/clang-tools-extra/clang-query/QueryProfile.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===--------- QueryProfile.h - clang-query ---------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PROFILE_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PROFILE_H
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/Timer.h"
-#include <optional>
-
-namespace llvm {
-class raw_ostream;
-} // namespace llvm
-
-namespace clang::query {
-
-class QueryProfile {
-public:
-  llvm::StringMap<llvm::TimeRecord> Records;
-  QueryProfile() = default;
-  ~QueryProfile();
-
-private:
-  std::optional<llvm::TimerGroup> TG;
-  void printUserFriendlyTable(llvm::raw_ostream &OS);
-};
-
-} // namespace clang::query
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_QUERY_QUERY_PROFILE_H



More information about the cfe-commits mailing list