[compiler-rt] r338347 - [XRay][compiler-rt] Profiling Mode: Include file header in buffers

Dean Michael Berris via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 30 21:16:55 PDT 2018


Author: dberris
Date: Mon Jul 30 21:16:54 2018
New Revision: 338347

URL: http://llvm.org/viewvc/llvm-project?rev=338347&view=rev
Log:
[XRay][compiler-rt] Profiling Mode: Include file header in buffers

Summary:
This change provides access to the file header even in the in-memory
buffer processing. This allows in-memory processing of the buffers to
also check the version, and the format, of the profile data.

Reviewers: eizan, kpw

Reviewed By: eizan

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D50037

Modified:
    compiler-rt/trunk/lib/xray/tests/unit/profile_collector_test.cc
    compiler-rt/trunk/lib/xray/xray_profile_collector.cc
    compiler-rt/trunk/lib/xray/xray_profiling.cc
    compiler-rt/trunk/test/xray/TestCases/Posix/profiling-multi-threaded.cc
    compiler-rt/trunk/test/xray/TestCases/Posix/profiling-single-threaded.cc

Modified: compiler-rt/trunk/lib/xray/tests/unit/profile_collector_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/tests/unit/profile_collector_test.cc?rev=338347&r1=338346&r2=338347&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/tests/unit/profile_collector_test.cc (original)
+++ compiler-rt/trunk/lib/xray/tests/unit/profile_collector_test.cc Mon Jul 30 21:16:54 2018
@@ -15,6 +15,8 @@
 #include "xray_profile_collector.h"
 #include "xray_profiling_flags.h"
 #include <cstdint>
+#include <cstring>
+#include <memory>
 #include <thread>
 #include <utility>
 #include <vector>
@@ -24,6 +26,29 @@ namespace {
 
 static constexpr auto kHeaderSize = 16u;
 
+constexpr uptr ExpectedProfilingVersion = 0x20180424;
+
+struct ExpectedProfilingFileHeader {
+  const u64 MagicBytes = 0x7872617970726f66; // Identifier for XRay profiling
+                                             // files 'xrayprof' in hex.
+  const uptr Version = ExpectedProfilingVersion;
+  uptr Timestamp = 0;
+  uptr PID = 0;
+};
+
+void ValidateFileHeaderBlock(XRayBuffer B) {
+  ASSERT_NE(static_cast<const void *>(B.Data), nullptr);
+  ASSERT_EQ(B.Size, sizeof(ExpectedProfilingFileHeader));
+  typename std::aligned_storage<sizeof(ExpectedProfilingFileHeader)>::type
+      FileHeaderStorage;
+  ExpectedProfilingFileHeader ExpectedHeader;
+  std::memcpy(&FileHeaderStorage, B.Data, B.Size);
+  auto &FileHeader =
+      *reinterpret_cast<ExpectedProfilingFileHeader *>(&FileHeaderStorage);
+  ASSERT_EQ(ExpectedHeader.MagicBytes, FileHeader.MagicBytes);
+  ASSERT_EQ(ExpectedHeader.Version, FileHeader.Version);
+}
+
 void ValidateBlock(XRayBuffer B) {
   profilingFlags()->setDefaults();
   ASSERT_NE(static_cast<const void *>(B.Data), nullptr);
@@ -107,9 +132,13 @@ TEST(profileCollectorServiceTest, PostSe
   // Then we serialize the data.
   profileCollectorService::serialize();
 
-  // Then we go through a single buffer to see whether we're getting the data we
-  // expect.
+  // Then we go through two buffers to see whether we're getting the data we
+  // expect. The first block must always be as large as a file header, which
+  // will have a fixed size.
   auto B = profileCollectorService::nextBuffer({nullptr, 0});
+  ValidateFileHeaderBlock(B);
+
+  B = profileCollectorService::nextBuffer(B);
   ValidateBlock(B);
   u32 BlockSize;
   u32 BlockNum;
@@ -169,6 +198,9 @@ TEST(profileCollectorServiceTest, PostSe
 
   // Ensure that we see two buffers.
   auto B = profileCollectorService::nextBuffer({nullptr, 0});
+  ValidateFileHeaderBlock(B);
+
+  B = profileCollectorService::nextBuffer(B);
   ValidateBlock(B);
 
   B = profileCollectorService::nextBuffer(B);

Modified: compiler-rt/trunk/lib/xray/xray_profile_collector.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_profile_collector.cc?rev=338347&r1=338346&r2=338347&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_profile_collector.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_profile_collector.cc Mon Jul 30 21:16:54 2018
@@ -37,6 +37,19 @@ struct ProfileBuffer {
   size_t Size;
 };
 
+// Current version of the profile format.
+constexpr u64 XRayProfilingVersion = 0x20180424;
+
+// Identifier for XRay profiling files 'xrayprof' in hex.
+constexpr u64 XRayMagicBytes = 0x7872617970726f66;
+
+struct XRayProfilingFileHeader {
+  const u64 MagicBytes = XRayMagicBytes;
+  const u64 Version = XRayProfilingVersion;
+  u64 Timestamp = 0; // System time in nanoseconds.
+  u64 PID = 0;       // Process ID.
+};
+
 struct BlockHeader {
   u32 BlockSize;
   u32 BlockNum;
@@ -302,7 +315,22 @@ XRayBuffer nextBuffer(XRayBuffer B) {
   if (ProfileBuffers == nullptr || ProfileBuffers->Size() == 0)
     return {nullptr, 0};
 
-  if (B.Data == nullptr)
+  static pthread_once_t Once = PTHREAD_ONCE_INIT;
+  static typename std::aligned_storage<sizeof(XRayProfilingFileHeader)>::type
+      FileHeaderStorage;
+  pthread_once(&Once,
+               +[] { new (&FileHeaderStorage) XRayProfilingFileHeader{}; });
+
+  if (UNLIKELY(B.Data == nullptr)) {
+    // The first buffer should always contain the file header information.
+    auto &FileHeader =
+        *reinterpret_cast<XRayProfilingFileHeader *>(&FileHeaderStorage);
+    FileHeader.Timestamp = NanoTime();
+    FileHeader.PID = internal_getpid();
+    return {&FileHeaderStorage, sizeof(XRayProfilingFileHeader)};
+  }
+
+  if (UNLIKELY(B.Data == &FileHeaderStorage))
     return {(*ProfileBuffers)[0].Data, (*ProfileBuffers)[0].Size};
 
   BlockHeader Header;

Modified: compiler-rt/trunk/lib/xray/xray_profiling.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_profiling.cc?rev=338347&r1=338346&r2=338347&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_profiling.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_profiling.cc Mon Jul 30 21:16:54 2018
@@ -32,16 +32,6 @@ 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};
 
@@ -144,14 +134,7 @@ XRayLogFlushStatus profilingFlush() XRAY
         if (Verbosity())
           Report("profiling: Failed to flush to file, 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
+        // Now for each of the buffers, write out the profile data as we would
         // see it in memory, verbatim.
         while (B.Data != nullptr && B.Size != 0) {
           retryingWriteAll(Fd, reinterpret_cast<const char *>(B.Data),

Modified: compiler-rt/trunk/test/xray/TestCases/Posix/profiling-multi-threaded.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/TestCases/Posix/profiling-multi-threaded.cc?rev=338347&r1=338346&r2=338347&view=diff
==============================================================================
--- compiler-rt/trunk/test/xray/TestCases/Posix/profiling-multi-threaded.cc (original)
+++ compiler-rt/trunk/test/xray/TestCases/Posix/profiling-multi-threaded.cc Mon Jul 30 21:16:54 2018
@@ -51,7 +51,8 @@ volatile int buffer_counter = 0;
   assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED);
   assert(__xray_log_process_buffers(process_buffer) ==
          XRayLogFlushStatus::XRAY_LOG_FLUSHED);
-  // We're running three threds, so we expect three buffers.
-  assert(buffer_counter == 3);
+  // We're running three threads, so we expect four buffers (including the file
+  // header buffer).
+  assert(buffer_counter == 4);
   assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
 }

Modified: compiler-rt/trunk/test/xray/TestCases/Posix/profiling-single-threaded.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/TestCases/Posix/profiling-single-threaded.cc?rev=338347&r1=338346&r2=338347&view=diff
==============================================================================
--- compiler-rt/trunk/test/xray/TestCases/Posix/profiling-single-threaded.cc (original)
+++ compiler-rt/trunk/test/xray/TestCases/Posix/profiling-single-threaded.cc Mon Jul 30 21:16:54 2018
@@ -47,7 +47,10 @@ volatile int buffer_counter = 0;
   f0();
   assert(__xray_log_process_buffers(process_buffer) ==
          XRayLogFlushStatus::XRAY_LOG_FLUSHED);
-  assert(buffer_counter == 1);
+  // There's always at least one buffer, containing the profile file header. We
+  // assert that we have two, to indicate that we're expecting exactly one
+  // thread's worth of data.
+  assert(buffer_counter == 2);
   assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
 
   // Let's reset the counter.
@@ -60,6 +63,6 @@ volatile int buffer_counter = 0;
   f0();
   assert(__xray_log_process_buffers(process_buffer) ==
          XRayLogFlushStatus::XRAY_LOG_FLUSHED);
-  assert(buffer_counter == 1);
+  assert(buffer_counter == 2);
   assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
 }




More information about the llvm-commits mailing list