[compiler-rt] r274964 - [esan] Add __esan_report for mid-run data

Derek Bruening via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 8 21:13:25 PDT 2016


Author: bruening
Date: Fri Jul  8 23:13:25 2016
New Revision: 274964

URL: http://llvm.org/viewvc/llvm-project?rev=274964&view=rev
Log:
[esan] Add __esan_report for mid-run data

Summary:
Adds a new public interface routine __esan_report() which can be used to
request profiling results prior to abnormal termination (e.g., for a server
process killed by its parent where the normal exit does not allow for
normal result reporting).

Implements this for the working-set tool.  The cache frag tool is left
unimplemented as it requires missing iteration capabilities.

Adds a new test.

Reviewers: aizatsky

Subscribers: vitalybuka, zhaoqin, kcc, eugenis, llvm-commits, kubabrecka

Differential Revision: http://reviews.llvm.org/D22098

Added:
    compiler-rt/trunk/include/sanitizer/esan_interface.h
    compiler-rt/trunk/test/esan/TestCases/workingset-midreport.cpp
Modified:
    compiler-rt/trunk/include/CMakeLists.txt
    compiler-rt/trunk/lib/esan/cache_frag.cpp
    compiler-rt/trunk/lib/esan/cache_frag.h
    compiler-rt/trunk/lib/esan/esan.cpp
    compiler-rt/trunk/lib/esan/esan.h
    compiler-rt/trunk/lib/esan/esan_interface.cpp
    compiler-rt/trunk/lib/esan/working_set.cpp
    compiler-rt/trunk/lib/esan/working_set.h
    compiler-rt/trunk/test/esan/lit.cfg

Modified: compiler-rt/trunk/include/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/CMakeLists.txt?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/include/CMakeLists.txt (original)
+++ compiler-rt/trunk/include/CMakeLists.txt Fri Jul  8 23:13:25 2016
@@ -4,6 +4,7 @@ set(SANITIZER_HEADERS
   sanitizer/common_interface_defs.h
   sanitizer/coverage_interface.h
   sanitizer/dfsan_interface.h
+  sanitizer/esan_interface.h
   sanitizer/linux_syscall_hooks.h
   sanitizer/lsan_interface.h
   sanitizer/msan_interface.h

Added: compiler-rt/trunk/include/sanitizer/esan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/esan_interface.h?rev=274964&view=auto
==============================================================================
--- compiler-rt/trunk/include/sanitizer/esan_interface.h (added)
+++ compiler-rt/trunk/include/sanitizer/esan_interface.h Fri Jul  8 23:13:25 2016
@@ -0,0 +1,46 @@
+//===-- sanitizer/esan_interface.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of EfficiencySanitizer, a family of performance tuners.
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ESAN_INTERFACE_H
+#define SANITIZER_ESAN_INTERFACE_H
+
+#include <sanitizer/common_interface_defs.h>
+
+// We declare our interface routines as weak to allow the user to avoid
+// ifdefs and instead use this pattern to allow building the same sources
+// with and without our runtime library:
+//     if (__esan_report)
+//       __esan_report();
+#ifdef _MSC_VER
+/* selectany is as close to weak as we'll get. */
+#define COMPILER_RT_WEAK __declspec(selectany)
+#elif __GNUC__
+#define COMPILER_RT_WEAK __attribute__((weak))
+#else
+#define COMPILER_RT_WEAK
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This function can be called mid-run (or at the end of a run for
+// a server process that doesn't shut down normally) to request that
+// data for that point in the run be reported from the tool.
+void COMPILER_RT_WEAK __esan_report();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_ESAN_INTERFACE_H

Modified: compiler-rt/trunk/lib/esan/cache_frag.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/cache_frag.cpp?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/cache_frag.cpp (original)
+++ compiler-rt/trunk/lib/esan/cache_frag.cpp Fri Jul  8 23:13:25 2016
@@ -199,4 +199,10 @@ int finalizeCacheFrag() {
   return 0;
 }
 
+void reportCacheFrag() {
+  VPrintf(2, "in esan::%s\n", __FUNCTION__);
+  // FIXME: Not yet implemented.  We need to iterate over all of the
+  // compilation unit data.
+}
+
 } // namespace __esan

Modified: compiler-rt/trunk/lib/esan/cache_frag.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/cache_frag.h?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/cache_frag.h (original)
+++ compiler-rt/trunk/lib/esan/cache_frag.h Fri Jul  8 23:13:25 2016
@@ -22,6 +22,7 @@ void processCacheFragCompilationUnitExit
 
 void initializeCacheFrag();
 int finalizeCacheFrag();
+void reportCacheFrag();
 
 } // namespace __esan
 

Modified: compiler-rt/trunk/lib/esan/esan.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan.cpp?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/esan.cpp (original)
+++ compiler-rt/trunk/lib/esan/esan.cpp Fri Jul  8 23:13:25 2016
@@ -228,6 +228,15 @@ int finalizeLibrary() {
   return 0;
 }
 
+void reportResults() {
+  VPrintf(1, "in esan::%s\n", __FUNCTION__);
+  if (__esan_which_tool == ESAN_CacheFrag) {
+    return reportCacheFrag();
+  } else if (__esan_which_tool == ESAN_WorkingSet) {
+    return reportWorkingSet();
+  }
+}
+
 void processCompilationUnitInit(void *Ptr) {
   VPrintf(2, "in esan::%s\n", __FUNCTION__);
   if (__esan_which_tool == ESAN_CacheFrag) {

Modified: compiler-rt/trunk/lib/esan/esan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan.h?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/esan.h (original)
+++ compiler-rt/trunk/lib/esan/esan.h Fri Jul  8 23:13:25 2016
@@ -37,6 +37,7 @@ extern bool EsanDuringInit;
 
 void initializeLibrary(ToolType Tool);
 int finalizeLibrary();
+void reportResults();
 // Esan creates the variable per tool per compilation unit at compile time
 // and passes its pointer Ptr to the runtime library.
 void processCompilationUnitInit(void *Ptr);

Modified: compiler-rt/trunk/lib/esan/esan_interface.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan_interface.cpp?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/esan_interface.cpp (original)
+++ compiler-rt/trunk/lib/esan/esan_interface.cpp Fri Jul  8 23:13:25 2016
@@ -109,3 +109,10 @@ void __esan_unaligned_loadN(void *Addr,
 void __esan_unaligned_storeN(void *Addr, uptr Size) {
   processRangeAccess(GET_CALLER_PC(), (uptr)Addr, Size, true);
 }
+
+// Public interface:
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE void __esan_report() {
+  reportResults();
+}
+} // extern "C"

Modified: compiler-rt/trunk/lib/esan/working_set.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/working_set.cpp?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/working_set.cpp (original)
+++ compiler-rt/trunk/lib/esan/working_set.cpp Fri Jul  8 23:13:25 2016
@@ -118,6 +118,8 @@ void processRangeAccessWorkingSet(uptr P
 }
 
 // This routine will word-align ShadowStart and ShadowEnd prior to scanning.
+// It does *not* clear for BitIdx==TotalWorkingSetBitIdx, as that top bit
+// measures the access during the entire execution and should never be cleared.
 static u32 countAndClearShadowValues(u32 BitIdx, uptr ShadowStart,
                                      uptr ShadowEnd) {
   u32 WorkingSetSize = 0;
@@ -127,6 +129,8 @@ static u32 countAndClearShadowValues(u32
   // Get word aligned start.
   ShadowStart = RoundDownTo(ShadowStart, sizeof(u32));
   bool Accum = getFlags()->record_snapshots && BitIdx < MaxAccumBitIdx;
+  // Do not clear the bit that measures access during the entire execution.
+  bool Clear = BitIdx < TotalWorkingSetBitIdx;
   for (u32 *Ptr = (u32 *)ShadowStart; Ptr < (u32 *)ShadowEnd; ++Ptr) {
     if ((*Ptr & WordValue) != 0) {
       byte *BytePtr = (byte *)Ptr;
@@ -139,8 +143,10 @@ static u32 countAndClearShadowValues(u32
           }
         }
       }
-      // Clear this bit from every shadow byte.
-      *Ptr &= ~WordValue;
+      if (Clear) {
+        // Clear this bit from every shadow byte.
+        *Ptr &= ~WordValue;
+      }
     }
   }
   return WorkingSetSize;
@@ -149,6 +155,8 @@ static u32 countAndClearShadowValues(u32
 // Scan shadow memory to calculate the number of cache lines being accessed,
 // i.e., the number of non-zero bits indexed by BitIdx in each shadow byte.
 // We also clear the lowest bits (most recent working set snapshot).
+// We do *not* clear for BitIdx==TotalWorkingSetBitIdx, as that top bit
+// measures the access during the entire execution and should never be cleared.
 static u32 computeWorkingSizeAndReset(u32 BitIdx) {
   u32 WorkingSetSize = 0;
   MemoryMappingLayout MemIter(true/*cache*/);
@@ -226,10 +234,9 @@ static u32 getSizeForPrinting(u32 NumOfC
   }
 }
 
-int finalizeWorkingSet() {
+void reportWorkingSet() {
   const char *Unit;
   if (getFlags()->record_snapshots) {
-    Thread.joinThread();
     u32 Freq = 1;
     Report(" Total number of samples: %u\n", SnapshotNum);
     for (u32 i = 0; i < NumFreq; ++i) {
@@ -243,7 +250,6 @@ int finalizeWorkingSet() {
                SizePerFreq[i][j]);
       }
       Freq = Freq << getFlags()->snapshot_step;
-      SizePerFreq[i].free();
     }
   }
 
@@ -252,6 +258,16 @@ int finalizeWorkingSet() {
   u32 Size = getSizeForPrinting(NumOfCachelines, Unit);
   Report(" %s: the total working set size: %u %s (%u cache lines)\n",
          SanitizerToolName, Size, Unit, NumOfCachelines);
+}
+
+int finalizeWorkingSet() {
+  if (getFlags()->record_snapshots)
+    Thread.joinThread();
+  reportWorkingSet();
+  if (getFlags()->record_snapshots) {
+    for (u32 i = 0; i < NumFreq; ++i)
+      SizePerFreq[i].free();
+  }
   return 0;
 }
 

Modified: compiler-rt/trunk/lib/esan/working_set.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/working_set.h?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/lib/esan/working_set.h (original)
+++ compiler-rt/trunk/lib/esan/working_set.h Fri Jul  8 23:13:25 2016
@@ -23,6 +23,7 @@ namespace __esan {
 void initializeWorkingSet();
 void initializeShadowWorkingSet();
 int finalizeWorkingSet();
+void reportWorkingSet();
 void processRangeAccessWorkingSet(uptr PC, uptr Addr, SIZE_T Size,
                                   bool IsWrite);
 

Added: compiler-rt/trunk/test/esan/TestCases/workingset-midreport.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/esan/TestCases/workingset-midreport.cpp?rev=274964&view=auto
==============================================================================
--- compiler-rt/trunk/test/esan/TestCases/workingset-midreport.cpp (added)
+++ compiler-rt/trunk/test/esan/TestCases/workingset-midreport.cpp Fri Jul  8 23:13:25 2016
@@ -0,0 +1,71 @@
+// RUN: %clang_esan_wset -O0 %s -o %t 2>&1
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN
+
+// RUN: %clang -O0 %s -o %t 2>&1
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ESAN
+
+#include <sanitizer/esan_interface.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+const int size = 0x1 << 25; // 523288 cache lines
+const int iters = 6;
+
+int main(int argc, char **argv) {
+  char *buf = (char *)mmap(0, size, PROT_READ | PROT_WRITE,
+                           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  // Try to increase the probability that the sideline thread is
+  // scheduled.  Unfortunately we can't do proper synchronization
+  // without some form of annotation or something.
+  sched_yield();
+  // Do enough work to get at least 4 samples.
+  for (int j = 0; j < iters; ++j) {
+    for (int i = 0; i < size; ++i)
+      buf[i] = i;
+    sched_yield();
+  }
+  // Ensure a non-esan build works without ifdefs:
+  if (__esan_report) {
+    // We should get 2 roughly identical reports:
+    __esan_report();
+  }
+  munmap(buf, size);
+  fprintf(stderr, "all done\n");
+  // CHECK-NO-ESAN:   all done
+  // We only check for a few samples here to reduce the chance of flakiness:
+  // CHECK-ESAN:      =={{[0-9]+}}== Total number of samples: {{[0-9]+}}
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}== Samples array #0 at period 20 ms
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   0: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   1: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   2: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   3: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #1 at period 80 ms
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   0: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #2 at period 320 ms
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #3 at period 1280 ms
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #4 at period 5120 ms
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #5 at period 20 sec
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #6 at period 81 sec
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #7 at period 327 sec
+  // CHECK-ESAN: {{.*}} EfficiencySanitizer: the total working set size: 32 MB (5242{{[0-9][0-9]}} cache lines)
+  // CHECK-ESAN-NEXT: all done
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}== Total number of samples: {{[0-9]+}}
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}== Samples array #0 at period 20 ms
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   0: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   1: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   2: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   3: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #1 at period 80 ms
+  // CHECK-ESAN-NEXT: =={{[0-9]+}}==#   0: {{[ 0-9]+}} {{KB|MB|Bytes}} ({{[ 0-9]+}} cache lines)
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #2 at period 320 ms
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #3 at period 1280 ms
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #4 at period 5120 ms
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #5 at period 20 sec
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #6 at period 81 sec
+  // CHECK-ESAN:      =={{[0-9]+}}== Samples array #7 at period 327 sec
+  // CHECK-ESAN: {{.*}} EfficiencySanitizer: the total working set size: 32 MB (5242{{[0-9][0-9]}} cache lines)
+  return 0;
+}

Modified: compiler-rt/trunk/test/esan/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/esan/lit.cfg?rev=274964&r1=274963&r2=274964&view=diff
==============================================================================
--- compiler-rt/trunk/test/esan/lit.cfg (original)
+++ compiler-rt/trunk/test/esan/lit.cfg Fri Jul  8 23:13:25 2016
@@ -23,6 +23,8 @@ unit_cxxflags = (["-I%s" % esan_incdir,
 def build_invocation(compile_flags):
   return " " + " ".join([config.clang] + compile_flags) + " "
 
+config.substitutions.append( ("%clang ",
+                              build_invocation(base_cflags)) )
 config.substitutions.append( ("%clang_esan_frag ",
                               build_invocation(frag_cflags)) )
 config.substitutions.append( ("%clang_esan_wset ",




More information about the llvm-commits mailing list