[llvm-cov] Multi-threaded implementation of prepareFileReports method.
Summary:
Local testing has demonstrated a great speed improvement, compare the following:
1) Existing version:
```
$ time llvm-cov show -format=html -output-dir=report -instr-profile=... ...
The tool has been launched: 00:00:00
Loading coverage data: 00:00:00
Get unique source files: 00:00:33
Creating an index out of the source files: 00:00:34
Going into prepareFileReports: 00:00:34
Going to emit summary information for each file: 00:28:55 <-- 28:21 min!
Going to emit links to files with no function: 00:28:55
Launching 32 threads for generating HTML files: 00:28:55
real 37m43.651s
user 112m5.540s
sys 7m39.872s
```
2) Multi-threaded version with 32 CPUs:
```
$ time llvm-cov show -format=html -output-dir=report -instr-profile=... ...
The tool has been launched: 00:00:00
Loading coverage data: 00:00:00
Get unique source files: 00:00:38
Creating an index out of the source files: 00:00:40
Going into prepareFileReports: 00:00:40
Preparing file reports using 32 threads: 00:00:40
# Creating thread tasks for the following number of files: 16422
Going to emit summary information for each file: 00:01:57 <-- 1:17 min!
Going to emit links to files with no function: 00:01:58
Launching 32 threads for generating HTML files: 00:01:58
real 11m2.044s
user 134m48.124s
sys 7m53.388s
```
Reviewers: vsk, morehouse
Reviewed By: vsk
Subscribers: Dor1s, llvm-commits, kcc
Differential Revision: https://reviews.llvm.org/D41206
llvm-svn: 321871
diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp
index 9c553a7..aafdc43 100644
--- a/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -16,6 +16,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/Threading.h"
#include <numeric>
using namespace llvm;
@@ -319,42 +321,60 @@
}
}
+void CoverageReport::prepareSingleFileReport(const StringRef Filename,
+ const coverage::CoverageMapping *Coverage,
+ const CoverageViewOptions &Options, const unsigned LCP,
+ FileCoverageSummary *FileReport, const CoverageFilter *Filters) {
+ for (const auto &Group : Coverage->getInstantiationGroups(Filename)) {
+ std::vector<FunctionCoverageSummary> InstantiationSummaries;
+ for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
+ if (!Filters->matches(*Coverage, *F))
+ continue;
+ auto InstantiationSummary = FunctionCoverageSummary::get(*Coverage, *F);
+ FileReport->addInstantiation(InstantiationSummary);
+ InstantiationSummaries.push_back(InstantiationSummary);
+ }
+ if (InstantiationSummaries.empty())
+ continue;
+
+ auto GroupSummary =
+ FunctionCoverageSummary::get(Group, InstantiationSummaries);
+
+ if (Options.Debug)
+ outs() << "InstantiationGroup: " << GroupSummary.Name << " with "
+ << "size = " << Group.size() << "\n";
+
+ FileReport->addFunction(GroupSummary);
+ }
+}
+
std::vector<FileCoverageSummary> CoverageReport::prepareFileReports(
const coverage::CoverageMapping &Coverage, FileCoverageSummary &Totals,
ArrayRef<std::string> Files, const CoverageViewOptions &Options,
const CoverageFilter &Filters) {
- std::vector<FileCoverageSummary> FileReports;
unsigned LCP = getRedundantPrefixLen(Files);
+ auto NumThreads = Options.NumThreads;
+
+ // If NumThreads is not specified, auto-detect a good default.
+ if (NumThreads == 0)
+ NumThreads =
+ std::max(1U, std::min(llvm::heavyweight_hardware_concurrency(),
+ unsigned(Files.size())));
+
+ ThreadPool Pool(NumThreads);
+
+ std::vector<FileCoverageSummary> FileReports;
+ FileReports.reserve(Files.size());
for (StringRef Filename : Files) {
- FileCoverageSummary Summary(Filename.drop_front(LCP));
-
- for (const auto &Group : Coverage.getInstantiationGroups(Filename)) {
- std::vector<FunctionCoverageSummary> InstantiationSummaries;
- for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
- if (!Filters.matches(Coverage, *F))
- continue;
- auto InstantiationSummary = FunctionCoverageSummary::get(Coverage, *F);
- Summary.addInstantiation(InstantiationSummary);
- Totals.addInstantiation(InstantiationSummary);
- InstantiationSummaries.push_back(InstantiationSummary);
- }
- if (InstantiationSummaries.empty())
- continue;
-
- auto GroupSummary =
- FunctionCoverageSummary::get(Group, InstantiationSummaries);
-
- if (Options.Debug)
- outs() << "InstantiationGroup: " << GroupSummary.Name << " with "
- << "size = " << Group.size() << "\n";
-
- Summary.addFunction(GroupSummary);
- Totals.addFunction(GroupSummary);
- }
-
- FileReports.push_back(Summary);
+ FileReports.emplace_back(Filename.drop_front(LCP));
+ Pool.async(&CoverageReport::prepareSingleFileReport, Filename,
+ &Coverage, Options, LCP, &FileReports.back(), &Filters);
}
+ Pool.wait();
+
+ for (const auto &FileReport : FileReports)
+ Totals += FileReport;
return FileReports;
}