https://github.com/ilovepi updated 
https://github.com/llvm/llvm-project/pull/141139

>From 7f51d821b16e71a8834f7560c25268bd02c264df Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulki...@google.com>
Date: Wed, 21 May 2025 09:50:32 -0700
Subject: [PATCH] [clang-doc] Reenable time trace support

This patch re-enables -ftime-trace support in clang-doc. Initial support
in #97644 was reverted, and never relanded. This patch adds back the
command line option, and leverages the RAII tracing infrastructure more
thoroughly.
---
 clang-tools-extra/clang-doc/BitcodeReader.cpp |   8 +
 .../clang-doc/HTMLMustacheGenerator.cpp       |  33 +-
 clang-tools-extra/clang-doc/Mapper.cpp        |  84 +++--
 .../clang-doc/Representation.cpp              |   6 +-
 clang-tools-extra/clang-doc/Representation.h  |   5 +-
 .../clang-doc/tool/ClangDocMain.cpp           | 292 +++++++++++-------
 6 files changed, 263 insertions(+), 165 deletions(-)

diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp 
b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index f8e338eb7c6ed..546dd0254ec01 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -9,6 +9,7 @@
 #include "BitcodeReader.h"
 #include "llvm/ADT/IndexedMap.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
 #include <optional>
 
@@ -672,6 +673,7 @@ llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, 
T I) {
 
 template <>
 llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
+  llvm::TimeTraceScope("Reducing infos", "readRecord");
   Record R;
   llvm::StringRef Blob;
   llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
@@ -683,6 +685,7 @@ llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, 
Reference *I) {
 // Read a block of records into a single info.
 template <typename T>
 llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
+  llvm::TimeTraceScope("Reducing infos", "readBlock");
   if (llvm::Error Err = Stream.EnterSubBlock(ID))
     return Err;
 
@@ -713,6 +716,7 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T 
I) {
 
 template <typename T>
 llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
+  llvm::TimeTraceScope("Reducing infos", "readSubBlock");
   switch (ID) {
   // Blocks can only have certain types of sub blocks.
   case BI_COMMENT_BLOCK_ID: {
@@ -819,6 +823,7 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned 
ID, T I) {
 
 ClangDocBitcodeReader::Cursor
 ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
+  llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock");
   BlockOrRecordID = 0;
 
   while (!Stream.AtEndOfStream()) {
@@ -880,6 +885,7 @@ llvm::Error ClangDocBitcodeReader::validateStream() {
 }
 
 llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
+  llvm::TimeTraceScope("Reducing infos", "readBlockInfoBlock");
   Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
       Stream.ReadBlockInfoBlock();
   if (!MaybeBlockInfo)
@@ -895,6 +901,7 @@ llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
 template <typename T>
 llvm::Expected<std::unique_ptr<Info>>
 ClangDocBitcodeReader::createInfo(unsigned ID) {
+  llvm::TimeTraceScope("Reducing infos", "createInfo");
   std::unique_ptr<Info> I = std::make_unique<T>();
   if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
     return std::move(Err);
@@ -903,6 +910,7 @@ ClangDocBitcodeReader::createInfo(unsigned ID) {
 
 llvm::Expected<std::unique_ptr<Info>>
 ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
+  llvm::TimeTraceScope("Reducing infos", "readBlockToInfo");
   switch (ID) {
   case BI_NAMESPACE_BLOCK_ID:
     return createInfo<NamespaceInfo>(ID);
diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp 
b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
index 366deb55b77b9..e34e1d052f197 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -18,6 +18,8 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Mustache.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/TimeProfiler.h"
 
 using namespace llvm;
 using namespace llvm::json;
@@ -81,13 +83,18 @@ static Error setupTemplateFiles(const 
clang::doc::ClangDocContext &CDCtx) {
 Error MustacheHTMLGenerator::generateDocs(
     StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos,
     const clang::doc::ClangDocContext &CDCtx) {
-  if (auto Err = setupTemplateFiles(CDCtx))
-    return Err;
+  {
+    llvm::TimeTraceScope TS("Setup Templates");
+    if (auto Err = setupTemplateFiles(CDCtx))
+      return Err;
+  }
+
   // Track which directories we already tried to create.
   StringSet<> CreatedDirs;
   // Collect all output by file name and create the necessary directories.
   StringMap<std::vector<doc::Info *>> FileToInfos;
   for (const auto &Group : Infos) {
+    llvm::TimeTraceScope TS("setup directories");
     doc::Info *Info = Group.getValue().get();
 
     SmallString<128> Path;
@@ -104,15 +111,19 @@ Error MustacheHTMLGenerator::generateDocs(
     FileToInfos[Path].push_back(Info);
   }
 
-  for (const auto &Group : FileToInfos) {
-    std::error_code FileErr;
-    raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_None);
-    if (FileErr)
-      return createFileOpenError(Group.getKey(), FileErr);
-
-    for (const auto &Info : Group.getValue())
-      if (Error Err = generateDocForInfo(Info, InfoOS, CDCtx))
-        return Err;
+  {
+    llvm::TimeTraceScope TS("Generate Docs");
+    for (const auto &Group : FileToInfos) {
+      llvm::TimeTraceScope TS("Info to Doc");
+      std::error_code FileErr;
+      raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_None);
+      if (FileErr)
+        return createFileOpenError(Group.getKey(), FileErr);
+
+      for (const auto &Info : Group.getValue())
+        if (Error Err = generateDocForInfo(Info, InfoOS, CDCtx))
+          return Err;
+    }
   }
   return Error::success();
 }
diff --git a/clang-tools-extra/clang-doc/Mapper.cpp 
b/clang-tools-extra/clang-doc/Mapper.cpp
index a17645c3f3a31..bbc8dc54ed4a3 100644
--- a/clang-tools-extra/clang-doc/Mapper.cpp
+++ b/clang-tools-extra/clang-doc/Mapper.cpp
@@ -13,7 +13,9 @@
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/Mutex.h"
+#include "llvm/Support/TimeProfiler.h"
 
 namespace clang {
 namespace doc {
@@ -40,48 +42,66 @@ Location MapASTVisitor::getDeclLocation(const NamedDecl *D) 
const {
 }
 
 void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
+  if (CDCtx.FTimeTrace)
+    llvm::timeTraceProfilerInitialize(200, "clang-doc");
   TraverseDecl(Context.getTranslationUnitDecl());
+  if (CDCtx.FTimeTrace)
+    llvm::timeTraceProfilerFinishThread();
 }
 
 template <typename T>
 bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) {
-  // If we're looking a decl not in user files, skip this decl.
-  if (D->getASTContext().getSourceManager().isInSystemHeader(D->getLocation()))
-    return true;
+  llvm::TimeTraceScope TS("Mapping declaration");
+  {
+    llvm::TimeTraceScope TS("Preamble");
+    // If we're looking a decl not in user files, skip this decl.
+    if (D->getASTContext().getSourceManager().isInSystemHeader(
+            D->getLocation()))
+      return true;
 
-  // Skip function-internal decls.
-  if (D->getParentFunctionOrMethod())
-    return true;
+    // Skip function-internal decls.
+    if (D->getParentFunctionOrMethod())
+      return true;
+  }
+
+  std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> CP;
 
-  llvm::SmallString<128> USR;
-  // If there is an error generating a USR for the decl, skip this decl.
-  if (index::generateUSRForDecl(D, USR))
-    return true;
-  // Prevent Visiting USR twice
   {
-    llvm::sys::SmartScopedLock<true> Guard(USRVisitedGuard);
-    StringRef Visited = USR.str();
-    if (USRVisited.count(Visited) && !isTypedefAnonRecord<T>(D))
+    llvm::TimeTraceScope TS("emit info from astnode");
+    llvm::SmallString<128> USR;
+    // If there is an error generating a USR for the decl, skip this decl.
+    if (index::generateUSRForDecl(D, USR))
       return true;
-    // We considered a USR to be visited only when its defined
-    if (IsDefinition)
-      USRVisited.insert(Visited);
+    // Prevent Visiting USR twice
+    {
+      llvm::sys::SmartScopedLock<true> Guard(USRVisitedGuard);
+      StringRef Visited = USR.str();
+      if (USRVisited.count(Visited) && !isTypedefAnonRecord<T>(D))
+        return true;
+      // We considered a USR to be visited only when its defined
+      if (IsDefinition)
+        USRVisited.insert(Visited);
+    }
+    bool IsFileInRootDir;
+    llvm::SmallString<128> File =
+        getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir);
+    CP = serialize::emitInfo(D, getComment(D, D->getASTContext()),
+                             getDeclLocation(D), CDCtx.PublicOnly);
+  }
+
+  auto &[Child, Parent] = CP;
+
+  {
+    llvm::TimeTraceScope TS("serialized info into bitcode");
+    // A null in place of a valid Info indicates that the serializer is 
skipping
+    // this decl for some reason (e.g. we're only reporting public decls).
+    if (Child)
+      CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Child->USR)),
+                               serialize::serialize(Child));
+    if (Parent)
+      CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Parent->USR)),
+                               serialize::serialize(Parent));
   }
-  bool IsFileInRootDir;
-  llvm::SmallString<128> File =
-      getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir);
-  auto [Child, Parent] =
-      serialize::emitInfo(D, getComment(D, D->getASTContext()),
-                          getDeclLocation(D), CDCtx.PublicOnly);
-
-  // A null in place of a valid Info indicates that the serializer is skipping
-  // this decl for some reason (e.g. we're only reporting public decls).
-  if (Child)
-    CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Child->USR)),
-                             serialize::serialize(Child));
-  if (Parent)
-    CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Parent->USR)),
-                             serialize::serialize(Parent));
   return true;
 }
 
diff --git a/clang-tools-extra/clang-doc/Representation.cpp 
b/clang-tools-extra/clang-doc/Representation.cpp
index 9ab2f342d969a..ad93ed66b86a1 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -369,9 +369,11 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext 
*ECtx,
                                  StringRef OutDirectory, StringRef SourceRoot,
                                  StringRef RepositoryUrl,
                                  StringRef RepositoryLinePrefix, StringRef 
Base,
-                                 std::vector<std::string> UserStylesheets)
+                                 std::vector<std::string> UserStylesheets,
+                                 bool FTimeTrace)
     : ECtx(ECtx), ProjectName(ProjectName), PublicOnly(PublicOnly),
-      OutDirectory(OutDirectory), UserStylesheets(UserStylesheets), Base(Base) 
{
+      FTimeTrace(FTimeTrace), OutDirectory(OutDirectory),
+      UserStylesheets(UserStylesheets), Base(Base) {
   llvm::SmallString<128> SourceRootDir(SourceRoot);
   if (SourceRoot.empty())
     // If no SourceRoot was provided the current path is used as the default
diff --git a/clang-tools-extra/clang-doc/Representation.h 
b/clang-tools-extra/clang-doc/Representation.h
index a2e01719eb59e..e7c67574da1e4 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -518,10 +518,13 @@ struct ClangDocContext {
   ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
                   bool PublicOnly, StringRef OutDirectory, StringRef 
SourceRoot,
                   StringRef RepositoryUrl, StringRef RepositoryCodeLinePrefix,
-                  StringRef Base, std::vector<std::string> UserStylesheets);
+                  StringRef Base, std::vector<std::string> UserStylesheets,
+                  bool FTimeTrace = false);
   tooling::ExecutionContext *ECtx;
   std::string ProjectName; // Name of project clang-doc is documenting.
   bool PublicOnly; // Indicates if only public declarations are documented.
+  bool FTimeTrace; // Indicates if ftime trace is turned on
+  int Granularity; // Granularity of ftime trace
   std::string OutDirectory; // Directory for outputting generated files.
   std::string SourceRoot;   // Directory where processed files are stored. 
Links
                             // to definition locations will only be generated 
if
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp 
b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 8e8f7053a8f87..7eba1f3826723 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -41,6 +41,7 @@
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
 #include <atomic>
 #include <mutex>
@@ -110,6 +111,11 @@ static llvm::cl::opt<std::string> RepositoryCodeLinePrefix(
     llvm::cl::desc("Prefix of line code for repository."),
     llvm::cl::cat(ClangDocCategory));
 
+static llvm::cl::opt<bool> FTimeTrace("ftime-trace", llvm::cl::desc(R"(
+Turn on time profiler. Generates clang-doc-tracing.json)"),
+                                      llvm::cl::init(false),
+                                      llvm::cl::cat(ClangDocCategory));
+
 enum OutputFormatTy {
   md,
   yaml,
@@ -256,140 +262,188 @@ Example usage for a project using a compile commands 
database:
     return 1;
   }
 
-  // Fail early if an invalid format was provided.
-  std::string Format = getFormatString();
-  llvm::outs() << "Emiting docs in " << Format << " format.\n";
-  auto G = doc::findGeneratorByName(Format);
-  if (!G) {
-    llvm::errs() << toString(G.takeError()) << "\n";
-    return 1;
-  }
-
-  ArgumentsAdjuster ArgAdjuster;
-  if (!DoxygenOnly)
-    ArgAdjuster = combineAdjusters(
-        getInsertArgumentAdjuster("-fparse-all-comments",
-                                  tooling::ArgumentInsertPosition::END),
-        ArgAdjuster);
-
-  clang::doc::ClangDocContext CDCtx = {
-      Executor->get()->getExecutionContext(),
-      ProjectName,
-      PublicOnly,
-      OutDirectory,
-      SourceRoot,
-      RepositoryUrl,
-      RepositoryCodeLinePrefix,
-      BaseDirectory,
-      {UserStylesheets.begin(), UserStylesheets.end()}};
-
-  if (Format == "html") {
-    if (auto Err = getHtmlAssetFiles(argv[0], CDCtx)) {
-      llvm::errs() << toString(std::move(Err)) << "\n";
-      return 1;
-    }
-  }
-
-  // Mapping phase
-  llvm::outs() << "Mapping decls...\n";
-  auto Err =
-      Executor->get()->execute(doc::newMapperActionFactory(CDCtx), 
ArgAdjuster);
-  if (Err) {
-    if (IgnoreMappingFailures)
-      llvm::errs() << "Error mapping decls in files. Clang-doc will ignore "
-                      "these files and continue:\n"
-                   << toString(std::move(Err)) << "\n";
-    else {
-      llvm::errs() << toString(std::move(Err)) << "\n";
+  // turns on ftime trace profiling
+  if (FTimeTrace)
+    llvm::timeTraceProfilerInitialize(200, "clang-doc");
+  {
+    llvm::TimeTraceScope("main");
+
+    // Fail early if an invalid format was provided.
+    std::string Format = getFormatString();
+    llvm::outs() << "Emiting docs in " << Format << " format.\n";
+    auto G = doc::findGeneratorByName(Format);
+    if (!G) {
+      llvm::errs() << toString(G.takeError()) << "\n";
       return 1;
     }
-  }
 
-  // Collect values into output by key.
-  // In ToolResults, the Key is the hashed USR and the value is the
-  // bitcode-encoded representation of the Info object.
-  llvm::outs() << "Collecting infos...\n";
-  llvm::StringMap<std::vector<StringRef>> USRToBitcode;
-  Executor->get()->getToolResults()->forEachResult(
-      [&](StringRef Key, StringRef Value) {
-        USRToBitcode[Key].emplace_back(Value);
-      });
-
-  // Collects all Infos according to their unique USR value. This map is added
-  // to from the thread pool below and is protected by the USRToInfoMutex.
-  llvm::sys::Mutex USRToInfoMutex;
-  llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
-
-  // First reducing phase (reduce all decls into one info per decl).
-  llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n";
-  std::atomic<bool> Error;
-  Error = false;
-  llvm::sys::Mutex IndexMutex;
-  // ExecutorConcurrency is a flag exposed by AllTUsExecution.h
-  llvm::DefaultThreadPool 
Pool(llvm::hardware_concurrency(ExecutorConcurrency));
-  for (auto &Group : USRToBitcode) {
-    Pool.async([&]() {
-      std::vector<std::unique_ptr<doc::Info>> Infos;
-      for (auto &Bitcode : Group.getValue()) {
-        llvm::BitstreamCursor Stream(Bitcode);
-        doc::ClangDocBitcodeReader Reader(Stream);
-        auto ReadInfos = Reader.readBitcode();
-        if (!ReadInfos) {
-          llvm::errs() << toString(ReadInfos.takeError()) << "\n";
-          Error = true;
-          return;
-        }
-        std::move(ReadInfos->begin(), ReadInfos->end(),
-                  std::back_inserter(Infos));
+    ArgumentsAdjuster ArgAdjuster;
+    if (!DoxygenOnly)
+      ArgAdjuster = combineAdjusters(
+          getInsertArgumentAdjuster("-fparse-all-comments",
+                                    tooling::ArgumentInsertPosition::END),
+          ArgAdjuster);
+
+    clang::doc::ClangDocContext CDCtx = {
+        Executor->get()->getExecutionContext(),
+        ProjectName,
+        PublicOnly,
+        OutDirectory,
+        SourceRoot,
+        RepositoryUrl,
+        RepositoryCodeLinePrefix,
+        BaseDirectory,
+        {UserStylesheets.begin(), UserStylesheets.end()},
+        FTimeTrace};
+
+    if (Format == "html") {
+      if (auto Err = getHtmlAssetFiles(argv[0], CDCtx)) {
+        llvm::errs() << toString(std::move(Err)) << "\n";
+        return 1;
       }
+    }
 
-      auto Reduced = doc::mergeInfos(Infos);
-      if (!Reduced) {
-        llvm::errs() << llvm::toString(Reduced.takeError());
-        return;
+    llvm::timeTraceProfilerBegin("Executor Launch", "total runtime");
+    // Mapping phase
+    llvm::outs() << "Mapping decls...\n";
+    auto Err = Executor->get()->execute(doc::newMapperActionFactory(CDCtx),
+                                        ArgAdjuster);
+    llvm::timeTraceProfilerEnd();
+    if (Err) {
+      if (IgnoreMappingFailures)
+        llvm::errs() << "Error mapping decls in files. Clang-doc will ignore "
+                        "these files and continue:\n"
+                     << toString(std::move(Err)) << "\n";
+      else {
+        llvm::errs() << toString(std::move(Err)) << "\n";
+        return 1;
       }
+    }
 
-      // Add a reference to this Info in the Index
-      {
-        std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
-        clang::doc::Generator::addInfoToIndex(CDCtx.Idx, Reduced.get().get());
+    // Collect values into output by key.
+    // In ToolResults, the Key is the hashed USR and the value is the
+    // bitcode-encoded representation of the Info object.
+    llvm::timeTraceProfilerBegin("Collect Info", "total runtime");
+    llvm::outs() << "Collecting infos...\n";
+    llvm::StringMap<std::vector<StringRef>> USRToBitcode;
+    Executor->get()->getToolResults()->forEachResult(
+        [&](StringRef Key, StringRef Value) {
+          USRToBitcode[Key].emplace_back(Value);
+        });
+    llvm::timeTraceProfilerEnd();
+
+    // Collects all Infos according to their unique USR value. This map is 
added
+    // to from the thread pool below and is protected by the USRToInfoMutex.
+    llvm::sys::Mutex USRToInfoMutex;
+    llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
+
+    // First reducing phase (reduce all decls into one info per decl).
+    llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n";
+    std::atomic<bool> Error;
+    Error = false;
+    llvm::sys::Mutex IndexMutex;
+    // ExecutorConcurrency is a flag exposed by AllTUsExecution.h
+    llvm::DefaultThreadPool Pool(
+        llvm::hardware_concurrency(ExecutorConcurrency));
+    {
+      llvm::TimeTraceScope TS("Reduce");
+      for (auto &Group : USRToBitcode) {
+        Pool.async([&]() {
+          if (FTimeTrace)
+            llvm::timeTraceProfilerInitialize(200, "clang-doc");
+
+          std::vector<std::unique_ptr<doc::Info>> Infos;
+          {
+            llvm::TimeTraceScope Red("decoding bitcode");
+            for (auto &Bitcode : Group.getValue()) {
+              llvm::BitstreamCursor Stream(Bitcode);
+              doc::ClangDocBitcodeReader Reader(Stream);
+              auto ReadInfos = Reader.readBitcode();
+              if (!ReadInfos) {
+                llvm::errs() << toString(ReadInfos.takeError()) << "\n";
+                Error = true;
+                return;
+              }
+              std::move(ReadInfos->begin(), ReadInfos->end(),
+                        std::back_inserter(Infos));
+            }
+          }
+
+          std::unique_ptr<doc::Info> Reduced;
+
+          {
+            llvm::TimeTraceScope Merge("merging bitcode");
+            auto ExpReduced = doc::mergeInfos(Infos);
+
+            if (!ExpReduced) {
+              llvm::errs() << llvm::toString(ExpReduced.takeError());
+              return;
+            }
+            Reduced = std::move(*ExpReduced);
+          }
+
+          // Add a reference to this Info in the Index
+          {
+            llvm::TimeTraceScope Merge("addInfoToIndex");
+            std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
+            clang::doc::Generator::addInfoToIndex(CDCtx.Idx, Reduced.get());
+          }
+          // Save in the result map (needs a lock due to threaded access).
+
+          {
+            llvm::TimeTraceScope Merge("USRToInfo");
+            std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
+            USRToInfo[Group.getKey()] = std::move(Reduced);
+          }
+
+          if (CDCtx.FTimeTrace)
+            llvm::timeTraceProfilerFinishThread();
+        });
       }
 
-      // Save in the result map (needs a lock due to threaded access).
-      {
-        std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
-        USRToInfo[Group.getKey()] = std::move(Reduced.get());
-      }
-    });
-  }
+      Pool.wait();
+    }
 
-  Pool.wait();
+    if (Error)
+      return 1;
 
-  if (Error)
-    return 1;
+    {
+      llvm::TimeTraceScope Sort("Sort USRToInfo");
+      sortUsrToInfo(USRToInfo);
+    }
 
-  sortUsrToInfo(USRToInfo);
+    llvm::timeTraceProfilerBegin("Writing output", "total runtime");
+    // Ensure the root output directory exists.
+    if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
+        Err != std::error_code()) {
+      llvm::errs() << "Failed to create directory '" << OutDirectory << "'\n";
+      return 1;
+    }
 
-  // Ensure the root output directory exists.
-  if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
-      Err != std::error_code()) {
-    llvm::errs() << "Failed to create directory '" << OutDirectory << "'\n";
-    return 1;
-  }
+    // Run the generator.
+    llvm::outs() << "Generating docs...\n";
+    if (auto Err =
+            G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) 
{
+      llvm::errs() << toString(std::move(Err)) << "\n";
+      return 1;
+    }
 
-  // Run the generator.
-  llvm::outs() << "Generating docs...\n";
-  if (auto Err =
-          G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) {
-    llvm::errs() << toString(std::move(Err)) << "\n";
-    return 1;
+    llvm::outs() << "Generating assets for docs...\n";
+    Err = G->get()->createResources(CDCtx);
+    if (Err) {
+      llvm::outs() << "warning: " << toString(std::move(Err)) << "\n";
+    }
+    llvm::timeTraceProfilerEnd();
   }
-
-  llvm::outs() << "Generating assets for docs...\n";
-  Err = G->get()->createResources(CDCtx);
-  if (Err) {
-    llvm::outs() << "warning: " << toString(std::move(Err)) << "\n";
+  if (FTimeTrace) {
+    std::error_code EC;
+    llvm::raw_fd_ostream OS("clang-doc-tracing.json", EC,
+                            llvm::sys::fs::OF_Text);
+    if (!EC) {
+      llvm::timeTraceProfilerWrite(OS);
+      llvm::timeTraceProfilerCleanup();
+    } else
+      return 1;
   }
-
   return 0;
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to