blob: 73b2b68ffc4590bd2bbb4d0b647d4b5415d269c7 [file] [log] [blame]
/*
* Copyright (C) 2018 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.
*/
#include "src/trace_processor/types/trace_processor_context.h"
#include <cstdint>
#include <memory>
#include <optional>
#include <utility>
#include "perfetto/base/logging.h"
#include "perfetto/trace_processor/basic_types.h"
#include "src/trace_processor/forwarding_trace_parser.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/clock_converter.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/cpu_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/machine_tracker.h"
#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
#include "src/trace_processor/importers/common/process_track_translation_table.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/registered_file_tracker.h"
#include "src/trace_processor/importers/common/sched_event_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/common/symbol_tracker.h"
#include "src/trace_processor/importers/common/trace_file_tracker.h"
#include "src/trace_processor/importers/common/track_compressor.h"
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
#include "src/trace_processor/importers/proto/proto_trace_reader.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/trace_reader_registry.h"
#include "src/trace_processor/types/trace_processor_context_ptr.h"
namespace perfetto::trace_processor {
namespace {
template <typename T>
using Ptr = TraceProcessorContextPtr<T>;
void InitPerTraceAndMachineState(TraceProcessorContext* context) {
// Per-machine state (legacy).
context->track_tracker = Ptr<TrackTracker>::MakeRoot(context);
context->track_compressor = Ptr<TrackCompressor>::MakeRoot(context);
context->slice_tracker = Ptr<SliceTracker>::MakeRoot(context);
context->slice_translation_table =
Ptr<SliceTranslationTable>::MakeRoot(context->storage.get());
context->flow_tracker = Ptr<FlowTracker>::MakeRoot(context);
context->process_track_translation_table =
Ptr<ProcessTrackTranslationTable>::MakeRoot(context->storage.get());
context->event_tracker = Ptr<EventTracker>::MakeRoot(context);
context->sched_event_tracker = Ptr<SchedEventTracker>::MakeRoot(context);
context->args_translation_table =
Ptr<ArgsTranslationTable>::MakeRoot(context->storage.get());
context->slice_tracker->SetOnSliceBeginCallback(
[context](TrackId track_id, SliceId slice_id) {
context->flow_tracker->ClosePendingEventsOnTrack(track_id, slice_id);
});
}
void InitPerMachineState(TraceProcessorContext* context, uint32_t machine_id) {
context->symbol_tracker = Ptr<SymbolTracker>::MakeRoot(context);
context->machine_tracker = Ptr<MachineTracker>::MakeRoot(context, machine_id);
context->process_tracker = Ptr<ProcessTracker>::MakeRoot(context);
context->clock_tracker = Ptr<ClockTracker>::MakeRoot(context);
context->mapping_tracker = Ptr<MappingTracker>::MakeRoot(context);
context->cpu_tracker = Ptr<CpuTracker>::MakeRoot(context);
context->stack_profile_tracker = Ptr<StackProfileTracker>::MakeRoot(context);
}
void CopyPerMachineState(const TraceProcessorContext* source,
TraceProcessorContext* dest) {
dest->symbol_tracker = source->symbol_tracker.Fork();
dest->machine_tracker = source->machine_tracker.Fork();
dest->process_tracker = source->process_tracker.Fork();
dest->clock_tracker = source->clock_tracker.Fork();
dest->mapping_tracker = source->mapping_tracker.Fork();
dest->cpu_tracker = source->cpu_tracker.Fork();
dest->stack_profile_tracker = source->stack_profile_tracker.Fork();
}
void InitPerTraceState(TraceProcessorContext* context, uint32_t raw_trace_id) {
context->trace_state = Ptr<TraceProcessorContext::TraceState>::MakeRoot(
TraceProcessorContext::TraceState{raw_trace_id});
context->content_analyzer = nullptr;
}
void CopyTraceState(const TraceProcessorContext* source,
TraceProcessorContext* dest) {
dest->trace_state = source->trace_state.Fork();
dest->content_analyzer = source->content_analyzer.Fork();
}
Ptr<TraceSorter> CreateSorter(TraceProcessorContext* context,
const Config& config) {
TraceSorter::EventHandling event_handling;
switch (config.parsing_mode) {
case ParsingMode::kDefault:
event_handling = TraceSorter::EventHandling::kSortAndPush;
break;
case ParsingMode::kTokenizeOnly:
event_handling = TraceSorter::EventHandling::kDrop;
break;
case ParsingMode::kTokenizeAndSort:
event_handling = TraceSorter::EventHandling::kSortAndDrop;
break;
}
if (config.enable_dev_features) {
auto it = config.dev_flags.find("drop-after-sort");
if (it != config.dev_flags.end() && it->second == "true") {
event_handling = TraceSorter::EventHandling::kSortAndDrop;
}
}
return Ptr<TraceSorter>::MakeRoot(context, TraceSorter::SortingMode::kDefault,
event_handling);
}
void InitGlobalState(TraceProcessorContext* context, const Config& config) {
// Global state.
context->config = config;
context->storage = Ptr<TraceStorage>::MakeRoot(config);
context->sorter = CreateSorter(context, config);
context->reader_registry = Ptr<TraceReaderRegistry>::MakeRoot();
context->global_args_tracker =
Ptr<GlobalArgsTracker>::MakeRoot(context->storage.get());
context->trace_file_tracker = Ptr<TraceFileTracker>::MakeRoot(context);
context->descriptor_pool_ = Ptr<DescriptorPool>::MakeRoot();
context->forked_context_state =
Ptr<TraceProcessorContext::ForkedContextState>::MakeRoot();
context->clock_converter = Ptr<ClockConverter>::MakeRoot(context);
context->track_group_idx_state =
Ptr<TrackCompressorGroupIdxState>::MakeRoot();
context->register_additional_proto_modules = nullptr;
// Per-Trace State (Miscategorized).
context->metadata_tracker =
Ptr<MetadataTracker>::MakeRoot(context->storage.get());
context->registered_file_tracker =
Ptr<RegisteredFileTracker>::MakeRoot(context);
context->uuid_state = Ptr<TraceProcessorContext::UuidState>::MakeRoot();
context->heap_graph_tracker = nullptr;
}
void CopyGlobalState(const TraceProcessorContext* source,
TraceProcessorContext* dest) {
// Global state.
dest->config = source->config;
dest->storage = source->storage.Fork();
dest->sorter = source->sorter.Fork();
dest->reader_registry = source->reader_registry.Fork();
dest->global_args_tracker = source->global_args_tracker.Fork();
dest->trace_file_tracker = source->trace_file_tracker.Fork();
dest->descriptor_pool_ = source->descriptor_pool_.Fork();
dest->forked_context_state = source->forked_context_state.Fork();
dest->clock_converter = source->clock_converter.Fork();
dest->track_group_idx_state = source->track_group_idx_state.Fork();
dest->register_additional_proto_modules =
source->register_additional_proto_modules;
// Per-Trace State (Miscategorized).
dest->metadata_tracker = source->metadata_tracker.Fork();
dest->registered_file_tracker = source->registered_file_tracker.Fork();
dest->uuid_state = source->uuid_state.Fork();
dest->heap_graph_tracker = source->heap_graph_tracker.Fork();
}
} // namespace
TraceProcessorContext::TraceProcessorContext() = default;
TraceProcessorContext::TraceProcessorContext(const Config& _config) {
InitGlobalState(this, _config);
}
TraceProcessorContext::~TraceProcessorContext() = default;
TraceProcessorContext* TraceProcessorContext::ForkContextForTrace(
uint32_t raw_trace_id,
uint32_t default_raw_machine_id) const {
auto [it, inserted] =
forked_context_state->trace_and_machine_to_context.Insert(
std::pair(raw_trace_id, default_raw_machine_id), nullptr);
if (inserted) {
auto context = std::make_unique<TraceProcessorContext>();
CopyGlobalState(this, context.get());
// Initialize per-trace state.
auto [trace_it, trace_inserted] =
forked_context_state->trace_to_context.Insert(raw_trace_id,
context.get());
if (trace_inserted) {
InitPerTraceState(context.get(), raw_trace_id);
} else {
CopyTraceState(*trace_it, context.get());
}
// Initialize per-machine state.
auto [machine_it, machine_inserted] =
forked_context_state->machine_to_context.Insert(default_raw_machine_id,
context.get());
if (machine_inserted) {
InitPerMachineState(context.get(), default_raw_machine_id);
} else {
CopyPerMachineState(*machine_it, context.get());
}
// Initialize per-trace & per-machine state.
InitPerTraceAndMachineState(context.get());
*it = std::move(context);
}
return it->get();
}
TraceProcessorContext*
TraceProcessorContext::ForkContextForMachineInCurrentTrace(
uint32_t raw_machine_id) const {
PERFETTO_CHECK(trace_state);
return ForkContextForTrace(trace_state->raw_trace_id, raw_machine_id);
}
std::optional<MachineId> TraceProcessorContext::machine_id() const {
if (!machine_tracker) {
// Doesn't require that |machine_tracker| is initialized, e.g. in unit
// tests.
return std::nullopt;
}
return machine_tracker->machine_id();
}
void TraceProcessorContext::DestroyParsingState() {
auto _storage = std::move(storage);
// TODO(b/309623584): Decouple from storage and remove from here. This
// function should only move storage and delete everything else.
auto _heap_graph_tracker = std::move(heap_graph_tracker);
auto _clock_converter = std::move(clock_converter);
// "to_ftrace" textual converter of the "raw" table requires remembering the
// kernel version (inside system_info_tracker) to know how to textualise
// sched_switch.prev_state bitflags.
auto _system_info_tracker = std::move(system_info_tracker);
// "__intrinsic_winscope_proto_to_args_with_defaults" and trace summarization
// both require the descriptor pool to be alive.
auto _descriptor_pool_ = std::move(descriptor_pool_);
this->~TraceProcessorContext();
new (this) TraceProcessorContext();
storage = std::move(_storage);
heap_graph_tracker = std::move(_heap_graph_tracker);
clock_converter = std::move(_clock_converter);
system_info_tracker = std::move(_system_info_tracker);
descriptor_pool_ = std::move(_descriptor_pool_);
}
} // namespace perfetto::trace_processor