blob: 115653abfe6ce9317376008986270cf4158be76a [file] [log] [blame]
/*
* 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 <cinttypes>
#include <functional>
#include <set>
#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<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)>
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<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();
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<GlobalCallstackTrie::Node*> 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<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)>
current_process_fill_header_;
uint64_t last_written_ = 0;
};
} // namespace profiling
} // namespace perfetto
#endif // SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_