| /* |
| * 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 <functional> |
| #include <set> |
| |
| #include <inttypes.h> |
| |
| #include "perfetto/trace/interned_data/interned_data.pbzero.h" |
| #include "perfetto/trace/profiling/profile_common.pbzero.h" |
| #include "perfetto/trace/profiling/profile_packet.pbzero.h" |
| #include "perfetto/trace/trace_packet.pbzero.h" |
| |
| #include "perfetto/ext/tracing/core/trace_writer.h" |
| |
| #include "src/profiling/memory/bookkeeping.h" |
| #include "src/profiling/memory/interner.h" |
| |
| namespace perfetto { |
| namespace profiling { |
| |
| void WriteFixedInternings(TraceWriter* trace_writer); |
| |
| class DumpState { |
| public: |
| class InternState { |
| private: |
| friend class DumpState; |
| |
| std::set<InternID> dumped_strings_; |
| std::set<InternID> dumped_frames_; |
| std::set<InternID> dumped_mappings_; |
| std::set<uint64_t> dumped_callstacks_; |
| |
| uint64_t next_index_ = 0; |
| }; |
| |
| DumpState( |
| TraceWriter* trace_writer, |
| std::function<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)> |
| process_fill_header, |
| InternState* 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 AddIdleBytes(uintptr_t callstack_id, uint64_t bytes); |
| |
| void WriteAllocation(const HeapTracker::CallstackAllocations& alloc, |
| bool dump_at_max_mode); |
| void DumpCallstacks(GlobalCallstackTrie* callsites); |
| |
| private: |
| void WriteMap(const Interned<Mapping> map); |
| void WriteFrame(const Interned<Frame> frame); |
| void WriteBuildIDString(const Interned<std::string>& str); |
| void WriteMappingPathString(const Interned<std::string>& str); |
| void WriteFunctionNameString(const Interned<std::string>& 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<uint64_t>(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(); |
| current_profile_packet_->set_index(intern_state_->next_index_++); |
| } |
| |
| uint64_t currently_written() { |
| return trace_writer_->written() - last_written_; |
| } |
| |
| protos::pbzero::ProfilePacket::ProcessHeapSamples* |
| GetCurrentProcessHeapSamples(); |
| protos::pbzero::InternedData* GetCurrentInternedData(); |
| |
| std::set<GlobalCallstackTrie::Node*> callstacks_to_dump_; |
| |
| TraceWriter* trace_writer_; |
| InternState* 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<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)> |
| current_process_fill_header_; |
| std::map<uintptr_t /* callstack_id */, uint64_t> current_process_idle_allocs_; |
| |
| uint64_t last_written_ = 0; |
| }; |
| |
| } // namespace profiling |
| } // namespace perfetto |
| |
| #endif // SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_ |