summaryrefslogtreecommitdiff
path: root/lib/xray
diff options
context:
space:
mode:
authorDean Michael Berris <dberris@google.com>2018-06-12 04:06:25 +0000
committerDean Michael Berris <dberris@google.com>2018-06-12 04:06:25 +0000
commit31049741a2a2c58ebe04fc2e13b62ae8398945f4 (patch)
tree3669e45b54390db233f5bef24ef5add39829e92d /lib/xray
parentda1b8bff539cef08140fb20b8e7ed0ae0c244df5 (diff)
[XRay][profiler] Part 5: Profiler File Writing
Summary: This is part of the larger XRay Profiling Mode effort. This patch implements the profile writing mechanism, to allow profiles collected through the profiler mode to be persisted to files. Follow-on patches would allow us to load these profiles and start converting/analysing them through the `llvm-xray` tool. Depends on D44620. Reviewers: echristo, kpw, pelikan Reviewed By: kpw Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D45998 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@334472 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/xray')
-rw-r--r--lib/xray/xray_profiling.cc56
-rw-r--r--lib/xray/xray_profiling_flags.inc3
2 files changed, 53 insertions, 6 deletions
diff --git a/lib/xray/xray_profiling.cc b/lib/xray/xray_profiling.cc
index 1e7922c1e..9a4dd90c6 100644
--- a/lib/xray/xray_profiling.cc
+++ b/lib/xray/xray_profiling.cc
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
#include <memory>
+#include <time.h>
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_flags.h"
@@ -31,6 +32,16 @@ namespace __xray {
namespace {
+constexpr uptr XRayProfilingVersion = 0x20180424;
+
+struct XRayProfilingFileHeader {
+ const u64 MagicBytes = 0x7872617970726f66; // Identifier for XRay profiling
+ // files 'xrayprof' in hex.
+ const uptr Version = XRayProfilingVersion;
+ uptr Timestamp = 0; // System time in nanoseconds.
+ uptr PID = 0; // Process ID.
+};
+
atomic_sint32_t ProfilerLogFlushStatus = {
XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING};
@@ -89,8 +100,6 @@ atomic_sint32_t ProfileFlushStatus = {
XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING};
XRayLogFlushStatus profilingFlush() XRAY_NEVER_INSTRUMENT {
- // When flushing, all we really do is reset the global state, and only when
- // the log has already been finalized.
if (atomic_load(&ProfilerLogStatus, memory_order_acquire) !=
XRayLogInitStatus::XRAY_LOG_FINALIZED) {
if (Verbosity())
@@ -106,6 +115,37 @@ XRayLogFlushStatus profilingFlush() XRAY_NEVER_INSTRUMENT {
Report("Not flushing profiles, implementation still finalizing.\n");
}
+ // At this point, we'll create the file that will contain the profile, but
+ // only if the options say so.
+ if (!profilingFlags()->no_flush) {
+ int Fd = -1;
+ Fd = getLogFD();
+ if (Fd == -1) {
+ if (__sanitizer::Verbosity())
+ Report(
+ "profiler: Failed to acquire a file descriptor, dropping data.\n");
+ } else {
+ XRayProfilingFileHeader Header;
+ Header.Timestamp = NanoTime();
+ Header.PID = internal_getpid();
+ retryingWriteAll(Fd, reinterpret_cast<const char *>(&Header),
+ reinterpret_cast<const char *>(&Header) +
+ sizeof(Header));
+
+ // Now for each of the threads, write out the profile data as we would see
+ // it in memory, verbatim.
+ XRayBuffer B = profileCollectorService::nextBuffer({nullptr, 0});
+ while (B.Data != nullptr && B.Size != 0) {
+ retryingWriteAll(Fd, reinterpret_cast<const char *>(B.Data),
+ reinterpret_cast<const char *>(B.Data) + B.Size);
+ B = profileCollectorService::nextBuffer(B);
+ }
+
+ // Then we close out the file.
+ internal_close(Fd);
+ }
+ }
+
profileCollectorService::reset();
atomic_store(&ProfilerLogStatus, XRayLogFlushStatus::XRAY_LOG_FLUSHED,
@@ -221,8 +261,13 @@ profilingLoggingInit(size_t BufferSize, size_t BufferMax, void *Options,
auto *F = profilingFlags();
F->setDefaults();
registerProfilerFlags(&ConfigParser, F);
- const char *ProfilerCompileFlags = profilingCompilerDefinedFlags();
- ConfigParser.ParseString(ProfilerCompileFlags);
+ ConfigParser.ParseString(profilingCompilerDefinedFlags());
+ const char *Env = GetEnv("XRAY_PROFILING_OPTIONS");
+ if (Env == nullptr)
+ Env = "";
+ ConfigParser.ParseString(Env);
+
+ // Then parse the configuration string provided.
ConfigParser.ParseString(static_cast<const char *>(Options));
if (Verbosity())
ReportUnrecognizedFlags();
@@ -265,8 +310,7 @@ bool profilingDynamicInitializer() XRAY_NEVER_INSTRUMENT {
F->setDefaults();
FlagParser ProfilingParser;
registerProfilerFlags(&ProfilingParser, F);
- const char *ProfilerCompileFlags = profilingCompilerDefinedFlags();
- ProfilingParser.ParseString(ProfilerCompileFlags);
+ ProfilingParser.ParseString(profilingCompilerDefinedFlags());
}
XRayLogImpl Impl{
diff --git a/lib/xray/xray_profiling_flags.inc b/lib/xray/xray_profiling_flags.inc
index 6381a0748..616bc83ad 100644
--- a/lib/xray/xray_profiling_flags.inc
+++ b/lib/xray/xray_profiling_flags.inc
@@ -24,3 +24,6 @@ XRAY_FLAG(int, grace_period_ms, 100,
"Profile collection will wait this much time in milliseconds before "
"resetting the global state. This gives a chance to threads to "
"notice that the profiler has been finalized and clean up.")
+XRAY_FLAG(bool, no_flush, false,
+ "Set to true if we want the profiling implementation to not write "
+ "out files.")