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,11 @@ URL of repository that hosts code.
99100Used 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+
102108enum OutputFormatTy {
103109 md,
104110 yaml,
@@ -229,6 +235,12 @@ Example usage for a project using a compile commands database:
229235 return 1 ;
230236 }
231237
238+ // turns on ftime trace profiling
239+ if (FTimeTrace)
240+ llvm::timeTraceProfilerInitialize (200 , " clang-doc" );
241+
242+ llvm::TimeTraceScope (" main" );
243+
232244 // Fail early if an invalid format was provided.
233245 std::string Format = getFormatString ();
234246 llvm::outs () << " Emiting docs in " << Format << " format.\n " ;
@@ -252,8 +264,8 @@ Example usage for a project using a compile commands database:
252264 OutDirectory,
253265 SourceRoot,
254266 RepositoryUrl,
255- {UserStylesheets.begin (), UserStylesheets.end ()}
256- };
267+ {UserStylesheets.begin (), UserStylesheets.end ()},
268+ FTimeTrace };
257269
258270 if (Format == " html" ) {
259271 if (auto Err = getHtmlAssetFiles (argv[0 ], CDCtx)) {
@@ -262,6 +274,7 @@ Example usage for a project using a compile commands database:
262274 }
263275 }
264276
277+ llvm::timeTraceProfilerBegin (" Mapping declaration" , " total runtime" );
265278 // Mapping phase
266279 llvm::outs () << " Mapping decls...\n " ;
267280 auto Err =
@@ -276,24 +289,28 @@ Example usage for a project using a compile commands database:
276289 return 1 ;
277290 }
278291 }
292+ llvm::timeTraceProfilerEnd ();
279293
280294 // Collect values into output by key.
281295 // In ToolResults, the Key is the hashed USR and the value is the
282296 // bitcode-encoded representation of the Info object.
297+ llvm::timeTraceProfilerBegin (" Collect Info" , " total runtime" );
283298 llvm::outs () << " Collecting infos...\n " ;
284299 llvm::StringMap<std::vector<StringRef>> USRToBitcode;
285300 Executor->get ()->getToolResults ()->forEachResult (
286301 [&](StringRef Key, StringRef Value) {
287302 auto R = USRToBitcode.try_emplace (Key, std::vector<StringRef>());
288303 R.first ->second .emplace_back (Value);
289304 });
305+ llvm::timeTraceProfilerEnd ();
290306
291307 // Collects all Infos according to their unique USR value. This map is added
292308 // to from the thread pool below and is protected by the USRToInfoMutex.
293309 llvm::sys::Mutex USRToInfoMutex;
294310 llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
295311
296312 // First reducing phase (reduce all decls into one info per decl).
313+ llvm::timeTraceProfilerBegin (" Reducing infos" , " total runtime" );
297314 llvm::outs () << " Reducing " << USRToBitcode.size () << " infos...\n " ;
298315 std::atomic<bool > Error;
299316 Error = false ;
@@ -302,8 +319,11 @@ Example usage for a project using a compile commands database:
302319 llvm::DefaultThreadPool Pool (llvm::hardware_concurrency (ExecutorConcurrency));
303320 for (auto &Group : USRToBitcode) {
304321 Pool.async ([&]() {
305- std::vector<std::unique_ptr<doc::Info>> Infos;
322+ if (FTimeTrace)
323+ llvm::timeTraceProfilerInitialize (200 , " clang-doc" );
306324
325+ llvm::timeTraceProfilerBegin (" Reducing infos" , " decoding bitcode" );
326+ std::vector<std::unique_ptr<doc::Info>> Infos;
307327 for (auto &Bitcode : Group.getValue ()) {
308328 llvm::BitstreamCursor Stream (Bitcode);
309329 doc::ClangDocBitcodeReader Reader (Stream);
@@ -316,32 +336,40 @@ Example usage for a project using a compile commands database:
316336 std::move (ReadInfos->begin (), ReadInfos->end (),
317337 std::back_inserter (Infos));
318338 }
339+ llvm::timeTraceProfilerEnd ();
319340
341+ llvm::timeTraceProfilerBegin (" Reducing infos" , " merging bitcode" );
320342 auto Reduced = doc::mergeInfos (Infos);
321343 if (!Reduced) {
322344 llvm::errs () << llvm::toString (Reduced.takeError ());
323345 return ;
324346 }
347+ llvm::timeTraceProfilerEnd ();
325348
326349 // Add a reference to this Info in the Index
327350 {
328351 std::lock_guard<llvm::sys::Mutex> Guard (IndexMutex);
329352 clang::doc::Generator::addInfoToIndex (CDCtx.Idx , Reduced.get ().get ());
330353 }
331-
332354 // Save in the result map (needs a lock due to threaded access).
355+
333356 {
334357 std::lock_guard<llvm::sys::Mutex> Guard (USRToInfoMutex);
335358 USRToInfo[Group.getKey ()] = std::move (Reduced.get ());
336359 }
360+
361+ if (CDCtx.FTimeTrace )
362+ llvm::timeTraceProfilerFinishThread ();
337363 });
338364 }
365+ llvm::timeTraceProfilerEnd ();
339366
340367 Pool.wait ();
341368
342369 if (Error)
343370 return 1 ;
344371
372+ llvm::timeTraceProfilerBegin (" Writing output" , " total runtime" );
345373 // Ensure the root output directory exists.
346374 if (std::error_code Err = llvm::sys::fs::create_directories (OutDirectory);
347375 Err != std::error_code ()) {
@@ -362,6 +390,16 @@ Example usage for a project using a compile commands database:
362390 if (Err) {
363391 llvm::outs () << " warning: " << toString (std::move (Err)) << " \n " ;
364392 }
365-
393+ llvm::timeTraceProfilerEnd ();
394+
395+ if (FTimeTrace) {
396+ std::error_code EC;
397+ llvm::raw_fd_ostream OS (" clang-doc-tracing.json" , EC,
398+ llvm::sys::fs::OF_Text);
399+ if (!EC)
400+ llvm::timeTraceProfilerWrite (OS);
401+ else
402+ return 1 ;
403+ }
366404 return 0 ;
367405}
0 commit comments