/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_ #define SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_ #include #include #include #include "perfetto/ext/tracing/core/trace_writer.h" #include "src/profiling/common/interner.h" #include "src/profiling/common/interning_output.h" #include "src/profiling/memory/bookkeeping.h" #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h" #include "protos/perfetto/trace/profiling/profile_common.pbzero.h" #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h" #include "protos/perfetto/trace/trace_packet.pbzero.h" namespace perfetto { namespace profiling { class DumpState { public: DumpState( TraceWriter* trace_writer, std::function process_fill_header, InterningOutputTracker* intern_state) : trace_writer_(trace_writer), intern_state_(intern_state), current_process_fill_header_(std::move(process_fill_header)) { MakeProfilePacket(); } // This should be a temporary object, only used on the stack for dumping a // single process. DumpState(const DumpState&) = delete; DumpState& operator=(const DumpState&) = delete; DumpState(DumpState&&) = delete; DumpState& operator=(DumpState&&) = delete; void WriteAllocation(const HeapTracker::CallstackAllocations& alloc, bool dump_at_max_mode); void DumpCallstacks(GlobalCallstackTrie* callsites); private: void WriteMap(const Interned map); void WriteFrame(const Interned frame); void WriteBuildIDString(const Interned& str); void WriteMappingPathString(const Interned& str); void WriteFunctionNameString(const Interned& str); void MakeTracePacket() { last_written_ = trace_writer_->written(); if (current_trace_packet_) current_trace_packet_->Finalize(); current_trace_packet_ = trace_writer_->NewTracePacket(); current_trace_packet_->set_timestamp( static_cast(base::GetBootTimeNs().count())); current_profile_packet_ = nullptr; current_interned_data_ = nullptr; current_process_heap_samples_ = nullptr; } void MakeProfilePacket() { MakeTracePacket(); current_profile_packet_ = current_trace_packet_->set_profile_packet(); uint64_t* next_index = intern_state_->HeapprofdNextIndexMutable(); current_profile_packet_->set_index((*next_index)++); } uint64_t currently_written() { return trace_writer_->written() - last_written_; } protos::pbzero::ProfilePacket::ProcessHeapSamples* GetCurrentProcessHeapSamples(); protos::pbzero::InternedData* GetCurrentInternedData(); std::set callstacks_to_dump_; TraceWriter* trace_writer_; InterningOutputTracker* intern_state_; protos::pbzero::ProfilePacket* current_profile_packet_ = nullptr; protos::pbzero::InternedData* current_interned_data_ = nullptr; TraceWriter::TracePacketHandle current_trace_packet_; protos::pbzero::ProfilePacket::ProcessHeapSamples* current_process_heap_samples_ = nullptr; std::function current_process_fill_header_; uint64_t last_written_ = 0; }; } // namespace profiling } // namespace perfetto #endif // SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_