blob: 79944beead577ba2fe7adfa990df344a623362e6 [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 <functional>
#include <set>
#include <inttypes.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 {
class DumpState {
public:
DumpState(TraceWriter* trace_writer, uint64_t* next_index)
: trace_writer_(trace_writer), next_index_(next_index) {
MakeProfilePacket();
// Explicitly reserve intern ID 0 for the empty string, so unset string
// fields get mapped to this.
auto interned_string = current_profile_packet_->add_strings();
constexpr const uint8_t kEmptyString[] = "";
interned_string->set_iid(0);
interned_string->set_str(kEmptyString, 0);
}
void StartProcessDump(
std::function<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)>
fill_process_header);
void AddIdleBytes(uintptr_t callstack_id, uint64_t bytes);
void WriteAllocation(const HeapTracker::CallstackAllocations& alloc);
void DumpCallstacks(GlobalCallstackTrie* callsites);
void RejectConcurrent(pid_t pid);
void Finalize() { current_trace_packet_->Finalize(); }
private:
void WriteMap(const Interned<Mapping> map);
void WriteFrame(const Interned<Frame> frame);
void WriteString(const Interned<std::string>& str);
void NewProfilePacket() {
current_profile_packet_->set_continued(true);
MakeProfilePacket();
}
void MakeProfilePacket() {
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_ = current_trace_packet_->set_profile_packet();
current_profile_packet_->set_index((*next_index_)++);
}
uint64_t currently_written() {
return trace_writer_->written() - last_written_;
}
protos::pbzero::ProfilePacket::ProcessHeapSamples*
GetCurrentProcessHeapSamples();
std::set<InternID> dumped_strings_;
std::set<InternID> dumped_frames_;
std::set<InternID> dumped_mappings_;
std::set<GlobalCallstackTrie::Node*> callstacks_to_dump_;
TraceWriter* trace_writer_;
protos::pbzero::ProfilePacket* current_profile_packet_;
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* next_index_;
uint64_t last_written_ = 0;
};
} // namespace profiling
} // namespace perfetto
#endif // SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_