Repository: kudu
Updated Branches:
  refs/heads/master 136b8058f -> 5d10a56f9


KUDU-2291 (part 1): allow collecting a thread's stack without immediate 
symbolization

For the /stacks page we would like to be able to grab the stack from a
bunch of threads as quickly as possible to eliminate "skid" between the
collection times. Symbolization of stacks is much slower than
collection, so this patch adds a new API to collect the remote thread
stack without symbolizing it immediately.

This adds a simple benchmark for remote thread stack collection. The
initial results are not that different between symbolized and
unsymbolized because the stack collection performance itself is poor.
This will be improved in a later patch in this series.

I0207 19:33:20.960477 30799 debug-util-test.cc:175] Throughput: 99 dumps/second 
(symbolize=0)
I0207 19:33:21.963946 30799 debug-util-test.cc:175] Throughput: 84 dumps/second 
(symbolize=1)

Change-Id: I0a14fbb7d0cafcd7b966dac507e71bae32e2cc1a
Reviewed-on: http://gerrit.cloudera.org:8080/9252
Tested-by: Kudu Jenkins
Reviewed-by: Will Berkeley <wdberke...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/f9b2ccc8
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/f9b2ccc8
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/f9b2ccc8

Branch: refs/heads/master
Commit: f9b2ccc874a9e643cf38966b3e25d927f4b19b1a
Parents: 136b805
Author: Todd Lipcon <t...@apache.org>
Authored: Wed Feb 7 18:27:54 2018 -0800
Committer: Todd Lipcon <t...@apache.org>
Committed: Tue Feb 13 20:33:44 2018 +0000

----------------------------------------------------------------------
 src/kudu/util/debug-util-test.cc | 27 +++++++++++++++++++++++++++
 src/kudu/util/debug-util.cc      | 30 +++++++++++++++++++++---------
 src/kudu/util/debug-util.h       |  4 ++++
 3 files changed, 52 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/f9b2ccc8/src/kudu/util/debug-util-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/debug-util-test.cc b/src/kudu/util/debug-util-test.cc
index 455f8cb..734b2d9 100644
--- a/src/kudu/util/debug-util-test.cc
+++ b/src/kudu/util/debug-util-test.cc
@@ -18,6 +18,7 @@
 #include <unistd.h>
 
 #include <csignal>
+#include <ostream>
 #include <string>
 #include <vector>
 
@@ -149,6 +150,32 @@ TEST_F(DebugUtilTest, TestDumpAllThreads) {
     LOG(INFO) << DumpThreadStack(tid);
   }
 }
+
+TEST_F(DebugUtilTest, Benchmark) {
+  CountDownLatch l(1);
+  scoped_refptr<Thread> t;
+  ASSERT_OK(Thread::Create("test", "test thread", &SleeperThread, &l, &t));
+  SCOPED_CLEANUP({
+      // Allow the thread to finish.
+      l.CountDown();
+      t->Join();
+    });
+
+  for (bool symbolize : {false, true}) {
+    MonoTime end_time = MonoTime::Now() + MonoDelta::FromSeconds(1);
+    int count = 0;
+    volatile int prevent_optimize = 0;
+    while (MonoTime::Now() < end_time) {
+      StackTrace trace;
+      GetThreadStack(t->tid(), &trace);
+      if (symbolize) {
+        prevent_optimize += trace.Symbolize().size();
+      }
+      count++;
+    }
+    LOG(INFO) << "Throughput: " << count << " dumps/second (symbolize=" << 
symbolize << ")";
+  }
+}
 #endif
 
 } // namespace kudu

http://git-wip-us.apache.org/repos/asf/kudu/blob/f9b2ccc8/src/kudu/util/debug-util.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/debug-util.cc b/src/kudu/util/debug-util.cc
index 1aea5c3..bd382a9 100644
--- a/src/kudu/util/debug-util.cc
+++ b/src/kudu/util/debug-util.cc
@@ -39,6 +39,7 @@
 #include "kudu/gutil/spinlock.h"
 #include "kudu/gutil/stringprintf.h"
 #include "kudu/gutil/strings/numbers.h"
+#include "kudu/gutil/strings/substitute.h"
 #include "kudu/util/debug/sanitizer_scopes.h"
 #include "kudu/util/errno.h"
 #include "kudu/util/monotime.h"
@@ -236,14 +237,14 @@ Status SetStackTraceSignal(int signum) {
   return Status::OK();
 }
 
-std::string DumpThreadStack(int64_t tid) {
+Status GetThreadStack(int64_t tid, StackTrace* stack) {
 #if defined(__linux__)
   base::SpinLockHolder h(&g_dumper_thread_lock);
 
   // Ensure that our signal handler is installed. We don't need any fancy 
GoogleOnce here
   // because of the mutex above.
   if (!InitSignalHandlerUnlocked(g_stack_trace_signum)) {
-    return "<unable to take thread stack: signal handler unavailable>";
+    return Status::NotSupported("unable to take thread stack: signal handler 
unavailable");
   }
 
   // Set the target TID in our communication structure, so if we end up with 
any
@@ -262,7 +263,7 @@ std::string DumpThreadStack(int64_t tid) {
       SignalCommunication::Lock l;
       g_comm.target_tid = 0;
     }
-    return "(unable to deliver signal: process may have exited)";
+    return Status::NotFound("unable to deliver signal: process may have 
exited");
   }
 
   // We give the thread ~1s to respond. In testing, threads typically respond 
within
@@ -282,21 +283,32 @@ std::string DumpThreadStack(int64_t tid) {
     SignalCommunication::Lock l;
     CHECK_EQ(tid, g_comm.target_tid);
 
+    g_comm.target_tid = 0;
     if (!g_comm.result_ready) {
-      ret = "(thread did not respond: maybe it is blocking signals)";
-    } else {
-      ret = g_comm.stack.Symbolize();
+      return Status::TimedOut("(thread did not respond: maybe it is blocking 
signals)");
     }
 
-    g_comm.target_tid = 0;
+    stack->CopyFrom(g_comm.stack);
+
     g_comm.result_ready = 0;
   }
-  return ret;
+  return Status::OK();
 #else // defined(__linux__)
-  return "(unsupported platform)";
+  return Status::NotSupported("unsupported platform");
 #endif
 }
 
+string DumpThreadStack(int64_t tid) {
+  StackTrace trace;
+  Status s = GetThreadStack(tid, &trace);
+  if (s.ok()) {
+    return trace.Symbolize();
+  }
+  return strings::Substitute("<$0>", s.ToString());
+}
+
+
+
 Status ListThreads(vector<pid_t> *tids) {
 #if defined(__linux__)
   DIR *dir = opendir("/proc/self/task/");

http://git-wip-us.apache.org/repos/asf/kudu/blob/f9b2ccc8/src/kudu/util/debug-util.h
----------------------------------------------------------------------
diff --git a/src/kudu/util/debug-util.h b/src/kudu/util/debug-util.h
index a84c04c..0d713b9 100644
--- a/src/kudu/util/debug-util.h
+++ b/src/kudu/util/debug-util.h
@@ -29,6 +29,8 @@
 
 namespace kudu {
 
+class StackTrace;
+
 // Return true if coverage is enabled.
 bool IsCoverageBuild();
 
@@ -59,6 +61,8 @@ Status SetStackTraceSignal(int signum);
 // may be active at a time.
 std::string DumpThreadStack(int64_t tid);
 
+Status GetThreadStack(int64_t tid, StackTrace* stack);
+
 // Return the current stack trace, stringified.
 std::string GetStackTrace();
 

Reply via email to