[clang-tools-extra] [clang-doc] Reenable time trace support (PR #141139)
Paul Kirth via cfe-commits
cfe-commits at lists.llvm.org
Fri May 30 16:54:50 PDT 2025
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/141139
>From feed17a330e088d068fc3a0a2eb127bda102f608 Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at 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 | 32 ++-
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 | 261 +++++++++++-------
6 files changed, 245 insertions(+), 151 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 65dc2e93582e8..8b7e4896c9fde 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -19,6 +19,7 @@
#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;
@@ -125,13 +126,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;
@@ -148,15 +154,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..9f640b5325da4 100644
--- a/clang-tools-extra/clang-doc/Mapper.cpp
+++ b/clang-tools-extra/clang-doc/Mapper.cpp
@@ -7,13 +7,13 @@
//===----------------------------------------------------------------------===//
#include "Mapper.h"
-#include "BitcodeWriter.h"
#include "Serialize.h"
#include "clang/AST/Comment.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/TimeProfiler.h"
namespace clang {
namespace doc {
@@ -40,48 +40,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 a3a6217f76bbd..0dbf73452fed6 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -524,10 +524,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 8253ef298db4d..0d2415c619217 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -35,6 +35,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>
@@ -104,6 +105,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, html, mustache };
static llvm::cl::opt<OutputFormatTy> FormatEnum(
@@ -286,115 +292,162 @@ Example usage for a project using a compile commands database:
auto Executor = ExitOnErr(clang::tooling::createExecutorFromCommandLineArgs(
argc, argv, ClangDocCategory, Overview));
- // Fail early if an invalid format was provided.
- std::string Format = getFormatString();
- llvm::outs() << "Emiting docs in " << Format << " format.\n";
- auto G = ExitOnErr(doc::findGeneratorByName(Format));
-
- ArgumentsAdjuster ArgAdjuster;
- if (!DoxygenOnly)
- ArgAdjuster = combineAdjusters(
- getInsertArgumentAdjuster("-fparse-all-comments",
- tooling::ArgumentInsertPosition::END),
- ArgAdjuster);
-
- clang::doc::ClangDocContext CDCtx = {
- Executor->getExecutionContext(),
- ProjectName,
- PublicOnly,
- OutDirectory,
- SourceRoot,
- RepositoryUrl,
- RepositoryCodeLinePrefix,
- BaseDirectory,
- {UserStylesheets.begin(), UserStylesheets.end()}};
-
- if (Format == "html") {
- ExitOnErr(getHtmlAssetFiles(argv[0], CDCtx));
- }
-
- if (Format == "mustache") {
- ExitOnErr(getMustacheHtmlFiles(argv[0], CDCtx));
- }
-
- // Mapping phase
- llvm::outs() << "Mapping decls...\n";
- ExitOnErr(handleMappingFailures(
- Executor->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster)));
-
- // 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->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));
- }
-
- auto Reduced = doc::mergeInfos(Infos);
- if (!Reduced) {
- llvm::errs() << llvm::toString(Reduced.takeError());
- return;
- }
-
- // 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());
- }
+ // 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 = ExitOnErr(doc::findGeneratorByName(Format));
+
+ ArgumentsAdjuster ArgAdjuster;
+ if (!DoxygenOnly)
+ ArgAdjuster = combineAdjusters(
+ getInsertArgumentAdjuster("-fparse-all-comments",
+ tooling::ArgumentInsertPosition::END),
+ ArgAdjuster);
+
+ clang::doc::ClangDocContext CDCtx = {
+ Executor->getExecutionContext(),
+ ProjectName,
+ PublicOnly,
+ OutDirectory,
+ SourceRoot,
+ RepositoryUrl,
+ RepositoryCodeLinePrefix,
+ BaseDirectory,
+ {UserStylesheets.begin(), UserStylesheets.end()},
+ FTimeTrace};
+
+ if (Format == "html") {
+ ExitOnErr(getHtmlAssetFiles(argv[0], CDCtx));
+ } else if (Format == "mustache") {
+ ExitOnErr(getMustacheHtmlFiles(argv[0], CDCtx));
+ }
- // 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());
+ llvm::timeTraceProfilerBegin("Executor Launch", "total runtime");
+ // Mapping phase
+ llvm::outs() << "Mapping decls...\n";
+ ExitOnErr(handleMappingFailures(
+ Executor->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster)));
+ llvm::timeTraceProfilerEnd();
+
+ // 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->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([&]() { // time trace decoding bitcode
+ 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));
+ }
+ } // time trace decoding bitcode
+
+ 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);
+ } // time trace merging bitcode
+
+ // 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();
+ });
}
- });
- }
- Pool.wait();
+ Pool.wait();
+ } // time trace reduce
- if (Error)
- return 1;
+ if (Error)
+ return 1;
- sortUsrToInfo(USRToInfo);
-
- // Ensure the root output directory exists.
- ExitOnErr(createDirectories(OutDirectory));
-
- // Run the generator.
- llvm::outs() << "Generating docs...\n";
- ExitOnErr(G->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx));
- llvm::outs() << "Generating assets for docs...\n";
- ExitOnErr(G->createResources(CDCtx));
+ {
+ llvm::TimeTraceScope Sort("Sort USRToInfo");
+ sortUsrToInfo(USRToInfo);
+ }
+ llvm::timeTraceProfilerBegin("Writing output", "total runtime");
+ // Ensure the root output directory exists.
+ ExitOnErr(createDirectories(OutDirectory));
+
+ // Run the generator.
+ llvm::outs() << "Generating docs...\n";
+
+ ExitOnErr(G->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx));
+ llvm::outs() << "Generating assets for docs...\n";
+ ExitOnErr(G->createResources(CDCtx));
+ llvm::timeTraceProfilerEnd();
+ } // time trace main
+
+ 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;
}
More information about the cfe-commits
mailing list