Merge "tp: migrate all tables to be Python based tables"
diff --git a/src/android_internal/statsd.h b/src/android_internal/statsd.h
index 8afa9f0..f114aa2 100644
--- a/src/android_internal/statsd.h
+++ b/src/android_internal/statsd.h
@@ -17,6 +17,7 @@
#ifndef SRC_ANDROID_INTERNAL_STATSD_H_
#define SRC_ANDROID_INTERNAL_STATSD_H_
+#include <stddef.h>
#include <stdint.h>
// This header declares proxy functions defined in
diff --git a/src/trace_processor/util/profile_builder.cc b/src/trace_processor/util/profile_builder.cc
index 869d9a6..bb99c71 100644
--- a/src/trace_processor/util/profile_builder.cc
+++ b/src/trace_processor/util/profile_builder.cc
@@ -200,6 +200,11 @@
: context_(*context),
string_table_(&result_, &context->storage->string_pool()),
annotations_(context) {
+ // Make sure the empty function always gets id 0 which will be ignored when
+ // writing the proto file.
+ functions_.insert(
+ {Function{kEmptyStringIndex, kEmptyStringIndex, kEmptyStringIndex},
+ kNullFunctionId});
WriteSampleTypes(sample_types);
}
@@ -409,8 +414,13 @@
uint64_t mapping_id) {
std::vector<Line> lines =
GetLinesForSymbolSetId(frame.symbol_set_id(), annotation, mapping_id);
- if (lines.empty()) {
- uint64_t function_id = WriteFunctionIfNeeded(frame, annotation, mapping_id);
+ if (!lines.empty()) {
+ return lines;
+ }
+
+ if (uint64_t function_id =
+ WriteFunctionIfNeeded(frame, annotation, mapping_id);
+ function_id != kNullFunctionId) {
lines.push_back({function_id, 0});
}
@@ -441,8 +451,11 @@
std::vector<GProfileBuilder::Line> lines;
for (const RowRef& symbol : symbol_set) {
- lines.push_back({WriteFunctionIfNeeded(symbol, annotation, mapping_id),
- symbol.line_number()});
+ if (uint64_t function_id =
+ WriteFunctionIfNeeded(symbol, annotation, mapping_id);
+ function_id != kNullFunctionId) {
+ lines.push_back({function_id, symbol.line_number()});
+ }
}
GetMapping(mapping_id).debug_info.has_inline_frames = true;
@@ -503,6 +516,11 @@
return name;
}
+int64_t GProfileBuilder::GetSystemNameForFrame(
+ const tables::StackProfileFrameTable::ConstRowReference& frame) {
+ return string_table_.InternString(frame.name());
+}
+
uint64_t GProfileBuilder::WriteFunctionIfNeeded(
const tables::StackProfileFrameTable::ConstRowReference& frame,
CallsiteAnnotation annotation,
@@ -515,7 +533,7 @@
auto ins = functions_.insert(
{Function{GetNameForFrame(frame, annotation),
- string_table_.InternString(frame.name()), kEmptyStringIndex},
+ GetSystemNameForFrame(frame), kEmptyStringIndex},
functions_.size() + 1});
uint64_t id = ins.first->second;
seen_functions_.insert({key, id});
@@ -530,6 +548,9 @@
void GProfileBuilder::WriteFunctions() {
for (const auto& entry : functions_) {
+ if (entry.second == kNullFunctionId) {
+ continue;
+ }
auto* func = result_->add_function();
func->set_id(entry.second);
if (entry.first.name != 0) {
diff --git a/src/trace_processor/util/profile_builder.h b/src/trace_processor/util/profile_builder.h
index 1fb18ec..8e24cb9 100644
--- a/src/trace_processor/util/profile_builder.h
+++ b/src/trace_processor/util/profile_builder.h
@@ -73,6 +73,7 @@
private:
static constexpr int64_t kEmptyStringIndex = 0;
+ static constexpr uint64_t kNullFunctionId = 0;
// Strings are stored in the `Profile` in a table and referenced by their
// index. This helper class takes care of all the book keeping.
@@ -269,6 +270,9 @@
const tables::StackProfileFrameTable::ConstRowReference& frame,
CallsiteAnnotation annotation);
+ int64_t GetSystemNameForFrame(
+ const tables::StackProfileFrameTable::ConstRowReference& frame);
+
uint64_t WriteLocationIfNeeded(FrameId frame_id,
CallsiteAnnotation annotation);
uint64_t WriteFakeLocationIfNeeded(const std::string& name);
@@ -276,8 +280,8 @@
uint64_t WriteFunctionIfNeeded(
const tables::SymbolTable::ConstRowReference& symbol,
CallsiteAnnotation annotation,
-
uint64_t mapping_id);
+
uint64_t WriteFunctionIfNeeded(
const tables::StackProfileFrameTable::ConstRowReference& frame,
CallsiteAnnotation annotation,
diff --git a/test/data/perf_sample_no_functions.pb.sha256 b/test/data/perf_sample_no_functions.pb.sha256
new file mode 100644
index 0000000..2800d93
--- /dev/null
+++ b/test/data/perf_sample_no_functions.pb.sha256
@@ -0,0 +1 @@
+45e09c54d964d390f92f60b673e3ff8fe83e4d7e904898a4b872ceb2e260af87
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/functions/tests.py b/test/trace_processor/diff_tests/functions/tests.py
index d68159a..7f952ed 100644
--- a/test/trace_processor/diff_tests/functions/tests.py
+++ b/test/trace_processor/diff_tests/functions/tests.py
@@ -31,6 +31,8 @@
stack.append("{name} ({address})".format(
name=profile.string_table[function.name],
address=hex(location.address)))
+ if len(location.line) == 0:
+ stack.append("({address})".format(address=hex(location.address)))
samples.append('Sample:\nValues: {values}\nStack:\n{stack}'.format(
values=', '.join(map(str, s.value)), stack='\n'.join(stack)))
return '\n\n'.join(sorted(samples)) + '\n'
@@ -287,6 +289,42 @@
}
"""))
+ def test_profile_no_functions(self):
+ return DiffTestBlueprint(
+ trace=DataPath("perf_sample_no_functions.pb"),
+ query="""
+ SELECT HEX(
+ EXPERIMENTAL_PROFILE(STACK_FROM_STACK_PROFILE_CALLSITE(callsite_id))
+ )
+ FROM PERF_SAMPLE
+ """,
+ out=BinaryProto(
+ message_type="perfetto.third_party.perftools.profiles.Profile",
+ post_processing=PrintProfileProto,
+ contents="""
+ Sample:
+ Values: 1
+ Stack:
+ (0x7a4167d3f8)
+ (0x783153c8e4)
+ (0x7a4161ef8c)
+ (0x7a42c3d8b0)
+ (0x7a4167d9f4)
+ (0x7a4163bc44)
+ (0x7a4172f330)
+ (0x7a4177a658)
+ (0x7a4162b3a0)
+
+ Sample:
+ Values: 1
+ Stack:
+ (0x7a4167d9f8)
+ (0x7a4163bc44)
+ (0x7a4172f330)
+ (0x7a4177a658)
+ (0x7a4162b3a0)
+ """))
+
def test_profile_default_sample_types(self):
return DiffTestBlueprint(
trace=DataPath("perf_sample.pb"),