summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2018-06-06 15:07:51 +0000
committerRoman Lebedev <lebedev.ri@gmail.com>2018-06-06 15:07:51 +0000
commita87f1d04cee8168c91d497f9589dc038b3863b14 (patch)
tree686d92842969cd48458986ca5e1d2f583df248f4 /clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp
parentc4b7e0125ffb7ccb66f39c8ebee32145a322c6b0 (diff)
downloadbcm5719-llvm-a87f1d04cee8168c91d497f9589dc038b3863b14.tar.gz
bcm5719-llvm-a87f1d04cee8168c91d497f9589dc038b3863b14.zip
[clang-tidy] Store checks profiling info as JSON files
Summary: Continuation of D46504. Example output: ``` $ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp $ # Note that there won't be timings table printed to the console. $ cat *.json { "file": "/path/to/source.cpp", "timestamp": "2018-05-16 16:13:18.717446360", "profile": { "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00, "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01, "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01 } } ``` There are two arguments that control profile storage: * `-store-check-profile=<prefix>` By default reports are printed in tabulated format to stderr. When this option is passed, these per-TU profiles are instead stored as JSON. If the prefix is not an absolute path, it is considered to be relative to the directory from where you have run :program:`clang-tidy`. All `.` and `..` patterns in the path are collapsed, and symlinks are resolved. Example: Let's suppose you have a source file named `example.cpp`, located in `/source` directory. * If you specify `-store-check-profile=/tmp`, then the profile will be saved to `/tmp/<timestamp>-example.cpp.json` * If you run :program:`clang-tidy` from within `/foo` directory, and specify `-store-check-profile=.`, then the profile will still be saved to `/foo/<timestamp>-example.cpp.json` Reviewers: alexfh, sbenza, george.karpenkov, NoQ, aaron.ballman Reviewed By: alexfh, george.karpenkov, aaron.ballman Subscribers: Quuxplusone, JonasToth, aaron.ballman, llvm-commits, rja, Eugene.Zelenko, xazax.hun, mgrang, cfe-commits Tags: #clang-tools-extra Differential Revision: https://reviews.llvm.org/D46602 llvm-svn: 334101
Diffstat (limited to 'clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp100
1 files changed, 64 insertions, 36 deletions
diff --git a/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp b/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp
index d332942fa24..fc0a9697b94 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyProfiling.cpp
@@ -9,56 +9,84 @@
#include "ClangTidyProfiling.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <system_error>
+#include <utility>
#define DEBUG_TYPE "clang-tidy-profiling"
namespace clang {
namespace tidy {
-void ClangTidyProfiling::preprocess() {
- // Convert from a insertion-friendly map to sort-friendly vector.
- Timers.clear();
- Timers.reserve(Records.size());
- for (const auto &P : Records) {
- Timers.emplace_back(P.getValue(), P.getKey());
- Total += P.getValue();
- }
- assert(Timers.size() == Records.size() && "Size mismatch after processing");
+ClangTidyProfiling::StorageParams::StorageParams(llvm::StringRef ProfilePrefix,
+ llvm::StringRef SourceFile)
+ : Timestamp(std::chrono::system_clock::now()), SourceFilename(SourceFile) {
+ llvm::SmallString<32> TimestampStr;
+ llvm::raw_svector_ostream OS(TimestampStr);
+ llvm::format_provider<decltype(Timestamp)>::format(Timestamp, OS,
+ "%Y%m%d%H%M%S%N");
+
+ llvm::SmallString<256> FinalPrefix(ProfilePrefix);
+ llvm::sys::path::append(FinalPrefix, TimestampStr);
- // We want the measurements to be sorted by decreasing time spent.
- llvm::sort(Timers.begin(), Timers.end());
+ // So the full output name is: /ProfilePrefix/timestamp-inputfilename.json
+ StoreFilename = llvm::Twine(FinalPrefix + "-" +
+ llvm::sys::path::filename(SourceFile) + ".json")
+ .str();
}
-void ClangTidyProfiling::printProfileData(llvm::raw_ostream &OS) const {
- std::string Line = "===" + std::string(73, '-') + "===\n";
- OS << Line;
-
- if (Total.getUserTime())
- OS << " ---User Time---";
- if (Total.getSystemTime())
- OS << " --System Time--";
- if (Total.getProcessTime())
- OS << " --User+System--";
- OS << " ---Wall Time---";
- if (Total.getMemUsed())
- OS << " ---Mem---";
- OS << " --- Name ---\n";
-
- // Loop through all of the timing data, printing it out.
- for (auto I = Timers.rbegin(), E = Timers.rend(); I != E; ++I) {
- I->first.print(Total, OS);
- OS << I->second << '\n';
- }
+void ClangTidyProfiling::printUserFriendlyTable(llvm::raw_ostream &OS) {
+ TG->print(OS);
+ OS.flush();
+}
- Total.print(Total, OS);
- OS << "Total\n";
- OS << Line << "\n";
+void ClangTidyProfiling::printAsJSON(llvm::raw_ostream &OS) {
+ OS << "{\n";
+ OS << "\"file\": \"" << Storage->SourceFilename << "\",\n";
+ OS << "\"timestamp\": \"" << Storage->Timestamp << "\",\n";
+ OS << "\"profile\": {\n";
+ TG->printJSONValues(OS, "");
+ OS << "\n}\n";
+ OS << "}\n";
OS.flush();
}
+void ClangTidyProfiling::storeProfileData() {
+ assert(Storage.hasValue() && "We should have a filename.");
+
+ llvm::SmallString<256> OutputDirectory(Storage->StoreFilename);
+ llvm::sys::path::remove_filename(OutputDirectory);
+ if (std::error_code EC = llvm::sys::fs::create_directories(OutputDirectory)) {
+ llvm::errs() << "Unable to create output directory '" << OutputDirectory
+ << "': " << EC.message() << "\n";
+ return;
+ }
+
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(Storage->StoreFilename, EC, llvm::sys::fs::F_None);
+ if (EC) {
+ llvm::errs() << "Error opening output file '" << Storage->StoreFilename
+ << "': " << EC.message() << "\n";
+ return;
+ }
+
+ printAsJSON(OS);
+}
+
+ClangTidyProfiling::ClangTidyProfiling(llvm::Optional<StorageParams> Storage)
+ : Storage(std::move(Storage)) {}
+
ClangTidyProfiling::~ClangTidyProfiling() {
- preprocess();
- printProfileData(llvm::errs());
+ TG.emplace("clang-tidy", "clang-tidy checks profiling", Records);
+
+ if (!Storage.hasValue())
+ printUserFriendlyTable(llvm::errs());
+ else
+ storeProfileData();
}
} // namespace tidy
OpenPOWER on IntegriCloud