Add max stack depth to agent
As a stack depth limit to the ti-alloc-sample agent. This will allow
the invocation to control how deep the stacks are, permitting better
flamegraphs.
Bug: none
Test: attach the agent; run the startop test; look at the log.
Change-Id: I3cee52c20c7e5034f5823a73ad8e2ce7efe42faa
diff --git a/tools/jvmti-agents/ti-alloc-sample/README.md b/tools/jvmti-agents/ti-alloc-sample/README.md
index bfd78a0..e4f3793 100644
--- a/tools/jvmti-agents/ti-alloc-sample/README.md
+++ b/tools/jvmti-agents/ti-alloc-sample/README.md
@@ -16,11 +16,13 @@
The agent is loaded using -agentpath like normal. It takes arguments in the
following format:
-> `sample_rate,log_path`
+> `sample_rate,stack_depth_limit,log_path`
* sample_rate is an integer specifying how frequently an event is reported.
E.g., 10 means every tenth call to new will be logged.
-* log_path is an absolued file path specifying where the log is to be written.
+* stack_depth_limit is an integer that determines the number of frames the deepest stack trace
+ can contain. It returns just the top portion if the limit is exceeded.
+* log_path is an absolute file path specifying where the log is to be written.
#### Output Format
diff --git a/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc b/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc
index 08ec434..f156421 100644
--- a/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc
+++ b/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc
@@ -324,6 +324,7 @@
}
static int sampling_rate = 10;
+static int stack_depth_limit = 50;
static void JNICALL logVMObjectAlloc(jvmtiEnv* jvmti,
JNIEnv* jni,
@@ -358,10 +359,13 @@
klass,
jlongContainer{.val = size}) + ")";
- static constexpr size_t kFrameDepthLimit = 20;
- jvmtiFrameInfo stack_frames[kFrameDepthLimit];
+ std::unique_ptr<jvmtiFrameInfo[]> stack_frames(new jvmtiFrameInfo[stack_depth_limit]);
jint stack_depth;
- jvmtiError err = jvmti->GetStackTrace(thread, 0, kFrameDepthLimit, stack_frames, &stack_depth);
+ jvmtiError err = jvmti->GetStackTrace(thread,
+ 0,
+ stack_depth_limit,
+ stack_frames.get(),
+ &stack_depth);
if (err == JVMTI_ERROR_NONE) {
for (int i = 0; i < stack_depth; ++i) {
record += "\n " + formatMethod(jvmti, stack_frames[i].method);
@@ -397,15 +401,24 @@
static jint AgentStart(JavaVM* vm,
char* options,
void* reserved ATTRIBUTE_UNUSED) {
- // options string should contain "sampling_rate,output_file_path".
+ // options string should contain "sampling_rate,stack_depth_limit,output_file_path".
std::string args(options);
size_t comma_pos = args.find(',');
if (comma_pos == std::string::npos) {
return JNI_ERR;
}
sampling_rate = std::stoi(args.substr(0, comma_pos));
+ args = args.substr(comma_pos + 1);
+ comma_pos = args.find(',');
+ if (comma_pos == std::string::npos) {
+ return JNI_ERR;
+ }
+ stack_depth_limit = std::stoi(args.substr(0, comma_pos));
std::string output_file_path = args.substr(comma_pos + 1);
+ LOG(INFO) << "Starting allocation tracing: sampling_rate=" << sampling_rate
+ << ", stack_depth_limit=" << stack_depth_limit;
+
// Create the environment.
jvmtiEnv* jvmti = nullptr;
if (SetupJvmtiEnv(vm, &jvmti) != JNI_OK) {