Skip to content

Commit cbb9d73

Browse files
committed
[clang-doc] add ftime trace
1 parent 10c894c commit cbb9d73

File tree

5 files changed

+72
-6
lines changed

5 files changed

+72
-6
lines changed

clang-tools-extra/clang-doc/BitcodeReader.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "BitcodeReader.h"
1010
#include "llvm/ADT/IndexedMap.h"
1111
#include "llvm/Support/Error.h"
12+
#include "llvm/Support/TimeProfiler.h"
1213
#include "llvm/Support/raw_ostream.h"
1314
#include <optional>
1415

@@ -670,6 +671,7 @@ llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
670671

671672
template <>
672673
llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
674+
llvm::TimeTraceScope("clang-doc", "readRecord Reference");
673675
Record R;
674676
llvm::StringRef Blob;
675677
llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
@@ -681,6 +683,7 @@ llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
681683
// Read a block of records into a single info.
682684
template <typename T>
683685
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
686+
llvm::TimeTraceScope("readBlock", "ClangDocBitcodeReader");
684687
if (llvm::Error Err = Stream.EnterSubBlock(ID))
685688
return Err;
686689

@@ -711,6 +714,7 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
711714

712715
template <typename T>
713716
llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
717+
llvm::TimeTraceScope("readSubBlock", "ClangDocBitcodeReader");
714718
switch (ID) {
715719
// Blocks can only have certain types of sub blocks.
716720
case BI_COMMENT_BLOCK_ID: {
@@ -817,6 +821,7 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
817821

818822
ClangDocBitcodeReader::Cursor
819823
ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
824+
llvm::TimeTraceScope("skipUntilRecordOrBlock", "ClangDocBitcodeReader");
820825
BlockOrRecordID = 0;
821826

822827
while (!Stream.AtEndOfStream()) {
@@ -878,6 +883,7 @@ llvm::Error ClangDocBitcodeReader::validateStream() {
878883
}
879884

880885
llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
886+
llvm::TimeTraceScope("readBlockInfoBlock", "ClangDocBitcodeReader");
881887
Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
882888
Stream.ReadBlockInfoBlock();
883889
if (!MaybeBlockInfo)
@@ -894,6 +900,7 @@ llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
894900
template <typename T>
895901
llvm::Expected<std::unique_ptr<Info>>
896902
ClangDocBitcodeReader::createInfo(unsigned ID) {
903+
llvm::TimeTraceScope("createInfo", "ClangDocBitcodeReader");
897904
std::unique_ptr<Info> I = std::make_unique<T>();
898905
if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
899906
return std::move(Err);
@@ -902,6 +909,7 @@ ClangDocBitcodeReader::createInfo(unsigned ID) {
902909

903910
llvm::Expected<std::unique_ptr<Info>>
904911
ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
912+
llvm::TimeTraceScope("readBlockToInfo", "ClangDocBitcodeReader");
905913
switch (ID) {
906914
case BI_NAMESPACE_BLOCK_ID:
907915
return createInfo<NamespaceInfo>(ID);

clang-tools-extra/clang-doc/Mapper.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@
1313
#include "clang/Index/USRGeneration.h"
1414
#include "llvm/ADT/StringExtras.h"
1515
#include "llvm/Support/Error.h"
16+
#include "llvm/Support/TimeProfiler.h"
1617

1718
namespace clang {
1819
namespace doc {
1920

2021
void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
22+
if (CDCtx.FTimeTrace)
23+
llvm::timeTraceProfilerInitialize(CDCtx.Granularity, "clang-doc");
2124
TraverseDecl(Context.getTranslationUnitDecl());
25+
if (CDCtx.FTimeTrace)
26+
llvm::timeTraceProfilerFinishThread();
2227
}
2328

2429
template <typename T> bool MapASTVisitor::mapDecl(const T *D) {
@@ -30,6 +35,7 @@ template <typename T> bool MapASTVisitor::mapDecl(const T *D) {
3035
if (D->getParentFunctionOrMethod())
3136
return true;
3237

38+
llvm::timeTraceProfilerBegin("emit info phase", "emit info");
3339
llvm::SmallString<128> USR;
3440
// If there is an error generating a USR for the decl, skip this decl.
3541
if (index::generateUSRForDecl(D, USR))
@@ -40,7 +46,9 @@ template <typename T> bool MapASTVisitor::mapDecl(const T *D) {
4046
auto I = serialize::emitInfo(D, getComment(D, D->getASTContext()),
4147
getLine(D, D->getASTContext()), File,
4248
IsFileInRootDir, CDCtx.PublicOnly);
49+
llvm::timeTraceProfilerEnd();
4350

51+
llvm::timeTraceProfilerBegin("serializing info", "serializing");
4452
// A null in place of I indicates that the serializer is skipping this decl
4553
// for some reason (e.g. we're only reporting public decls).
4654
if (I.first)
@@ -49,6 +57,7 @@ template <typename T> bool MapASTVisitor::mapDecl(const T *D) {
4957
if (I.second)
5058
CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(I.second->USR)),
5159
serialize::serialize(I.second));
60+
llvm::timeTraceProfilerEnd();
5261
return true;
5362
}
5463

clang-tools-extra/clang-doc/Representation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,12 @@ void Index::sort() {
366366

367367
ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
368368
StringRef ProjectName, bool PublicOnly,
369+
bool FTimeTrace, int Granularity,
369370
StringRef OutDirectory, StringRef SourceRoot,
370371
StringRef RepositoryUrl,
371372
std::vector<std::string> UserStylesheets)
372373
: ECtx(ECtx), ProjectName(ProjectName), PublicOnly(PublicOnly),
374+
FTimeTrace(FTimeTrace), Granularity(Granularity),
373375
OutDirectory(OutDirectory), UserStylesheets(UserStylesheets) {
374376
llvm::SmallString<128> SourceRootDir(SourceRoot);
375377
if (SourceRoot.empty())

clang-tools-extra/clang-doc/Representation.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,12 +480,15 @@ mergeInfos(std::vector<std::unique_ptr<Info>> &Values);
480480
struct ClangDocContext {
481481
ClangDocContext() = default;
482482
ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
483-
bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
483+
bool PublicOnly, bool FTimeTrace, int Granularity,
484+
StringRef OutDirectory, StringRef SourceRoot,
484485
StringRef RepositoryUrl,
485486
std::vector<std::string> UserStylesheets);
486487
tooling::ExecutionContext *ECtx;
487488
std::string ProjectName; // Name of project clang-doc is documenting.
488489
bool PublicOnly; // Indicates if only public declarations are documented.
490+
bool FTimeTrace; // Indicates if ftime trace is turned on
491+
int Granularity; // Granularity of ftime trace
489492
std::string OutDirectory; // Directory for outputting generated files.
490493
std::string SourceRoot; // Directory where processed files are stored. Links
491494
// to definition locations will only be generated if

clang-tools-extra/clang-doc/tool/ClangDocMain.cpp

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "llvm/Support/Process.h"
4242
#include "llvm/Support/Signals.h"
4343
#include "llvm/Support/ThreadPool.h"
44+
#include "llvm/Support/TimeProfiler.h"
4445
#include "llvm/Support/raw_ostream.h"
4546
#include <atomic>
4647
#include <mutex>
@@ -99,6 +100,16 @@ URL of repository that hosts code.
99100
Used for links to definition locations.)"),
100101
llvm::cl::cat(ClangDocCategory));
101102

103+
static llvm::cl::opt<bool> FTimeTrace("ftime-trace", llvm::cl::desc(R"(
104+
Turn on time profiler. Generates clang-doc-tracing.json)"),
105+
llvm::cl::init(false),
106+
llvm::cl::cat(ClangDocCategory));
107+
108+
static llvm::cl::opt<int> FTimeGranularity("ftime-gran", llvm::cl::desc(R"(
109+
Specify granularity for ftime-trace defaults to 200)"),
110+
llvm::cl::init(200),
111+
llvm::cl::cat(ClangDocCategory));
112+
102113
enum OutputFormatTy {
103114
md,
104115
yaml,
@@ -229,6 +240,12 @@ Example usage for a project using a compile commands database:
229240
return 1;
230241
}
231242

243+
// turns on ftime trace profiling
244+
if (FTimeTrace)
245+
llvm::timeTraceProfilerInitialize(FTimeGranularity, "clang-doc");
246+
247+
llvm::TimeTraceScope("clang-doc", "main");
248+
232249
// Fail early if an invalid format was provided.
233250
std::string Format = getFormatString();
234251
llvm::outs() << "Emiting docs in " << Format << " format.\n";
@@ -249,11 +266,12 @@ Example usage for a project using a compile commands database:
249266
Executor->get()->getExecutionContext(),
250267
ProjectName,
251268
PublicOnly,
269+
FTimeTrace,
270+
FTimeGranularity,
252271
OutDirectory,
253272
SourceRoot,
254273
RepositoryUrl,
255-
{UserStylesheets.begin(), UserStylesheets.end()}
256-
};
274+
{UserStylesheets.begin(), UserStylesheets.end()}};
257275

258276
if (Format == "html") {
259277
if (auto Err = getHtmlAssetFiles(argv[0], CDCtx)) {
@@ -262,6 +280,7 @@ Example usage for a project using a compile commands database:
262280
}
263281
}
264282

283+
llvm::timeTraceProfilerBegin("mapping phase", "mapping");
265284
// Mapping phase
266285
llvm::outs() << "Mapping decls...\n";
267286
auto Err =
@@ -276,24 +295,28 @@ Example usage for a project using a compile commands database:
276295
return 1;
277296
}
278297
}
298+
llvm::timeTraceProfilerEnd();
279299

280300
// Collect values into output by key.
281301
// In ToolResults, the Key is the hashed USR and the value is the
282302
// bitcode-encoded representation of the Info object.
303+
llvm::timeTraceProfilerBegin("clang-doc", "collection phase");
283304
llvm::outs() << "Collecting infos...\n";
284305
llvm::StringMap<std::vector<StringRef>> USRToBitcode;
285306
Executor->get()->getToolResults()->forEachResult(
286307
[&](StringRef Key, StringRef Value) {
287308
auto R = USRToBitcode.try_emplace(Key, std::vector<StringRef>());
288309
R.first->second.emplace_back(Value);
289310
});
311+
llvm::timeTraceProfilerEnd();
290312

291313
// Collects all Infos according to their unique USR value. This map is added
292314
// to from the thread pool below and is protected by the USRToInfoMutex.
293315
llvm::sys::Mutex USRToInfoMutex;
294316
llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
295317

296318
// First reducing phase (reduce all decls into one info per decl).
319+
llvm::timeTraceProfilerBegin("reduction phase", "reducing");
297320
llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n";
298321
std::atomic<bool> Error;
299322
Error = false;
@@ -302,8 +325,11 @@ Example usage for a project using a compile commands database:
302325
llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(ExecutorConcurrency));
303326
for (auto &Group : USRToBitcode) {
304327
Pool.async([&]() {
305-
std::vector<std::unique_ptr<doc::Info>> Infos;
328+
if (FTimeTrace)
329+
llvm::timeTraceProfilerInitialize(FTimeGranularity, "clang-doc");
306330

331+
llvm::timeTraceProfilerBegin("decoding bitcode phase", "decoding");
332+
std::vector<std::unique_ptr<doc::Info>> Infos;
307333
for (auto &Bitcode : Group.getValue()) {
308334
llvm::BitstreamCursor Stream(Bitcode);
309335
doc::ClangDocBitcodeReader Reader(Stream);
@@ -316,32 +342,39 @@ Example usage for a project using a compile commands database:
316342
std::move(ReadInfos->begin(), ReadInfos->end(),
317343
std::back_inserter(Infos));
318344
}
345+
llvm::timeTraceProfilerEnd();
319346

347+
llvm::timeTraceProfilerBegin("merging bitcode phase", "merging");
320348
auto Reduced = doc::mergeInfos(Infos);
321349
if (!Reduced) {
322350
llvm::errs() << llvm::toString(Reduced.takeError());
323351
return;
324352
}
353+
llvm::timeTraceProfilerEnd();
325354

326355
// Add a reference to this Info in the Index
327356
{
328357
std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
329358
clang::doc::Generator::addInfoToIndex(CDCtx.Idx, Reduced.get().get());
330359
}
331-
332360
// Save in the result map (needs a lock due to threaded access).
333361
{
334362
std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
335363
USRToInfo[Group.getKey()] = std::move(Reduced.get());
336364
}
365+
366+
if (CDCtx.FTimeTrace)
367+
llvm::timeTraceProfilerFinishThread();
337368
});
338369
}
370+
llvm::timeTraceProfilerEnd();
339371

340372
Pool.wait();
341373

342374
if (Error)
343375
return 1;
344376

377+
llvm::timeTraceProfilerBegin("generating phase", "generating");
345378
// Ensure the root output directory exists.
346379
if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
347380
Err != std::error_code()) {
@@ -362,6 +395,17 @@ Example usage for a project using a compile commands database:
362395
if (Err) {
363396
llvm::outs() << "warning: " << toString(std::move(Err)) << "\n";
364397
}
365-
398+
llvm::timeTraceProfilerEnd();
399+
400+
if (FTimeTrace) {
401+
std::error_code EC;
402+
llvm::raw_fd_ostream OS("clang-doc-tracing.json", EC,
403+
llvm::sys::fs::OF_Text);
404+
if (!EC) {
405+
llvm::timeTraceProfilerWrite(OS);
406+
} else {
407+
llvm::errs() << "Error opening file: " << EC.message() << "\n";
408+
}
409+
}
366410
return 0;
367411
}

0 commit comments

Comments
 (0)