41
41
#include " llvm/Support/Process.h"
42
42
#include " llvm/Support/Signals.h"
43
43
#include " llvm/Support/ThreadPool.h"
44
+ #include " llvm/Support/TimeProfiler.h"
44
45
#include " llvm/Support/raw_ostream.h"
45
46
#include < atomic>
46
47
#include < mutex>
47
48
#include < string>
48
- #include < exception>
49
- #include < typeinfo>
50
- #include < stdexcept>
51
-
52
49
53
50
using namespace clang ::ast_matchers;
54
51
using namespace clang ::tooling;
@@ -103,6 +100,11 @@ URL of repository that hosts code.
103
100
Used for links to definition locations.)" ),
104
101
llvm::cl::cat(ClangDocCategory));
105
102
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
+
106
108
enum OutputFormatTy {
107
109
md,
108
110
yaml,
@@ -209,19 +211,6 @@ llvm::Error getHtmlAssetFiles(const char *Argv0,
209
211
return getDefaultAssetFiles (Argv0, CDCtx);
210
212
}
211
213
212
- void handle_eptr (std::exception_ptr eptr) // passing by value is OK
213
- {
214
- try
215
- {
216
- if (eptr)
217
- std::rethrow_exception (eptr);
218
- }
219
- catch (const std::exception& e)
220
- {
221
- llvm::outs () << " Caught exception: '" << e.what () << " '\n " ;
222
- }
223
- }
224
-
225
214
int main (int argc, const char **argv) {
226
215
llvm::sys::PrintStackTraceOnErrorSignal (argv[0 ]);
227
216
std::error_code OK;
@@ -246,9 +235,14 @@ Example usage for a project using a compile commands database:
246
235
return 1 ;
247
236
}
248
237
238
+ // turns on ftime trace profiling
239
+ if (FTimeTrace)
240
+ llvm::timeTraceProfilerInitialize (200 , " clang-doc" );
241
+
242
+ llvm::TimeTraceScope (" main" );
243
+
249
244
// Fail early if an invalid format was provided.
250
245
std::string Format = getFormatString ();
251
- llvm::outs () << " Unoptimized\n " ;
252
246
llvm::outs () << " Emiting docs in " << Format << " format.\n " ;
253
247
auto G = doc::findGeneratorByName (Format);
254
248
if (!G) {
@@ -270,8 +264,8 @@ Example usage for a project using a compile commands database:
270
264
OutDirectory,
271
265
SourceRoot,
272
266
RepositoryUrl,
273
- {UserStylesheets.begin (), UserStylesheets.end ()}
274
- };
267
+ {UserStylesheets.begin (), UserStylesheets.end ()},
268
+ FTimeTrace };
275
269
276
270
if (Format == " html" ) {
277
271
if (auto Err = getHtmlAssetFiles (argv[0 ], CDCtx)) {
@@ -280,6 +274,7 @@ Example usage for a project using a compile commands database:
280
274
}
281
275
}
282
276
277
+ llvm::timeTraceProfilerBegin (" Mapping declaration" , " total runtime" );
283
278
// Mapping phase
284
279
llvm::outs () << " Mapping decls...\n " ;
285
280
auto Err =
@@ -294,24 +289,28 @@ Example usage for a project using a compile commands database:
294
289
return 1 ;
295
290
}
296
291
}
292
+ llvm::timeTraceProfilerEnd ();
297
293
298
294
// Collect values into output by key.
299
295
// In ToolResults, the Key is the hashed USR and the value is the
300
296
// bitcode-encoded representation of the Info object.
297
+ llvm::timeTraceProfilerBegin (" Collect Info" , " total runtime" );
301
298
llvm::outs () << " Collecting infos...\n " ;
302
299
llvm::StringMap<std::vector<StringRef>> USRToBitcode;
303
300
Executor->get ()->getToolResults ()->forEachResult (
304
301
[&](StringRef Key, StringRef Value) {
305
302
auto R = USRToBitcode.try_emplace (Key, std::vector<StringRef>());
306
303
R.first ->second .emplace_back (Value);
307
304
});
305
+ llvm::timeTraceProfilerEnd ();
308
306
309
307
// Collects all Infos according to their unique USR value. This map is added
310
308
// to from the thread pool below and is protected by the USRToInfoMutex.
311
309
llvm::sys::Mutex USRToInfoMutex;
312
310
llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
313
311
314
312
// First reducing phase (reduce all decls into one info per decl).
313
+ llvm::timeTraceProfilerBegin (" Reducing infos" , " total runtime" );
315
314
llvm::outs () << " Reducing " << USRToBitcode.size () << " infos...\n " ;
316
315
std::atomic<bool > Error;
317
316
Error = false ;
@@ -320,50 +319,57 @@ Example usage for a project using a compile commands database:
320
319
llvm::DefaultThreadPool Pool (llvm::hardware_concurrency (ExecutorConcurrency));
321
320
for (auto &Group : USRToBitcode) {
322
321
Pool.async ([&]() {
323
- try {
324
- std::vector<std::unique_ptr<doc::Info>> Infos;
325
- for (auto &Bitcode : Group.getValue ()) {
326
- llvm::BitstreamCursor Stream (Bitcode);
327
- doc::ClangDocBitcodeReader Reader (Stream);
328
- auto ReadInfos = Reader.readBitcode ();
329
- if (!ReadInfos) {
330
- llvm::errs () << toString (ReadInfos.takeError ()) << " \n " ;
331
- Error = true ;
332
- return ;
333
- }
334
- std::move (ReadInfos->begin (), ReadInfos->end (),
335
- std::back_inserter (Infos));
336
- }
337
-
338
- auto Reduced = doc::mergeInfos (Infos);
339
- if (!Reduced) {
340
- llvm::errs () << llvm::toString (Reduced.takeError ());
322
+ if (FTimeTrace)
323
+ llvm::timeTraceProfilerInitialize (200 , " clang-doc" );
324
+
325
+ llvm::timeTraceProfilerBegin (" Reducing infos" , " decoding bitcode" );
326
+ std::vector<std::unique_ptr<doc::Info>> Infos;
327
+ for (auto &Bitcode : Group.getValue ()) {
328
+ llvm::BitstreamCursor Stream (Bitcode);
329
+ doc::ClangDocBitcodeReader Reader (Stream);
330
+ auto ReadInfos = Reader.readBitcode ();
331
+ if (!ReadInfos) {
332
+ llvm::errs () << toString (ReadInfos.takeError ()) << " \n " ;
333
+ Error = true ;
341
334
return ;
342
335
}
336
+ std::move (ReadInfos->begin (), ReadInfos->end (),
337
+ std::back_inserter (Infos));
338
+ }
339
+ llvm::timeTraceProfilerEnd ();
343
340
344
- // Add a reference to this Info in the Index
345
- {
346
- std::lock_guard<llvm::sys::Mutex> Guard (IndexMutex);
347
- clang::doc::Generator::addInfoToIndex (CDCtx.Idx , Reduced.get ().get ());
348
- }
341
+ llvm::timeTraceProfilerBegin (" Reducing infos" , " merging bitcode" );
342
+ auto Reduced = doc::mergeInfos (Infos);
343
+ if (!Reduced) {
344
+ llvm::errs () << llvm::toString (Reduced.takeError ());
345
+ return ;
346
+ }
347
+ llvm::timeTraceProfilerEnd ();
349
348
350
- // Save in the result map (needs a lock due to threaded access).
351
- {
352
- std::lock_guard<llvm::sys::Mutex> Guard (USRToInfoMutex);
353
- USRToInfo[Group.getKey ()] = std::move (Reduced.get ());
354
- }
355
- } catch (...) {
356
- std::exception_ptr P = std::current_exception ();
357
- handle_eptr (P);
349
+ // Add a reference to this Info in the Index
350
+ {
351
+ std::lock_guard<llvm::sys::Mutex> Guard (IndexMutex);
352
+ clang::doc::Generator::addInfoToIndex (CDCtx.Idx , Reduced.get ().get ());
353
+ }
354
+ // Save in the result map (needs a lock due to threaded access).
355
+
356
+ {
357
+ std::lock_guard<llvm::sys::Mutex> Guard (USRToInfoMutex);
358
+ USRToInfo[Group.getKey ()] = std::move (Reduced.get ());
358
359
}
360
+
361
+ if (CDCtx.FTimeTrace )
362
+ llvm::timeTraceProfilerFinishThread ();
359
363
});
360
364
}
365
+ llvm::timeTraceProfilerEnd ();
361
366
362
367
Pool.wait ();
363
368
364
369
if (Error)
365
370
return 1 ;
366
371
372
+ llvm::timeTraceProfilerBegin (" Writing output" , " total runtime" );
367
373
// Ensure the root output directory exists.
368
374
if (std::error_code Err = llvm::sys::fs::create_directories (OutDirectory);
369
375
Err != std::error_code ()) {
@@ -384,6 +390,16 @@ Example usage for a project using a compile commands database:
384
390
if (Err) {
385
391
llvm::outs () << " warning: " << toString (std::move (Err)) << " \n " ;
386
392
}
387
-
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
+ }
388
404
return 0 ;
389
405
}
0 commit comments