Remove base/trace_event/ Change-Id: If14b91e0adfcebd178728abf55677802fc758e8f Reviewed-on: https://gn-review.googlesource.com/1405 Reviewed-by: Brett Wilson <brettw@chromium.org> Commit-Queue: Scott Graham <scottmg@chromium.org>
diff --git a/base/debug/task_annotator.cc b/base/debug/task_annotator.cc index 2197b85..def2d7a 100644 --- a/base/debug/task_annotator.cc +++ b/base/debug/task_annotator.cc
@@ -11,7 +11,6 @@ #include "base/no_destructor.h" #include "base/pending_task.h" #include "base/threading/thread_local.h" -#include "base/trace_event/trace_event.h" namespace base { namespace debug { @@ -37,13 +36,6 @@ void TaskAnnotator::DidQueueTask(const char* queue_function, const PendingTask& pending_task) { - if (queue_function) { - TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), - queue_function, - TRACE_ID_MANGLE(GetTaskTraceID(pending_task)), - TRACE_EVENT_FLAG_FLOW_OUT); - } - // TODO(https://crbug.com/826902): Fix callers that invoke DidQueueTask() // twice for the same PendingTask. // DCHECK(!pending_task.task_backtrace[0]) @@ -64,13 +56,6 @@ PendingTask* pending_task) { ScopedTaskRunActivity task_activity(*pending_task); - if (queue_function) { - TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), - queue_function, - TRACE_ID_MANGLE(GetTaskTraceID(*pending_task)), - TRACE_EVENT_FLAG_FLOW_IN); - } - // Before running the task, store the task backtrace with the chain of // PostTasks that resulted in this call and deliberately alias it to ensure // it is on the stack if the task crashes. Be careful not to assume that the
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc index c58d686..75677d4 100644 --- a/base/files/file_path_watcher_linux.cc +++ b/base/files/file_path_watcher_linux.cc
@@ -36,7 +36,6 @@ #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "base/trace_event/trace_event.h" namespace base {
diff --git a/base/memory/memory_pressure_listener.cc b/base/memory/memory_pressure_listener.cc index 669fb17..3768283 100644 --- a/base/memory/memory_pressure_listener.cc +++ b/base/memory/memory_pressure_listener.cc
@@ -5,7 +5,6 @@ #include "base/memory/memory_pressure_listener.h" #include "base/observer_list_threadsafe.h" -#include "base/trace_event/trace_event.h" namespace base {
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc index 6b53551..f868eb2 100644 --- a/base/memory/shared_memory_posix.cc +++ b/base/memory/shared_memory_posix.cc
@@ -23,7 +23,6 @@ #include "base/scoped_generic.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" -#include "base/trace_event/trace_event.h" #include "base/unguessable_token.h" #include "build_config.h"
diff --git a/base/memory/shared_memory_tracker.cc b/base/memory/shared_memory_tracker.cc index 5ca7c84..ee2b490 100644 --- a/base/memory/shared_memory_tracker.cc +++ b/base/memory/shared_memory_tracker.cc
@@ -6,9 +6,6 @@ #include "base/memory/shared_memory.h" #include "base/strings/string_number_conversions.h" -#include "base/trace_event/memory_allocator_dump_guid.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/process_memory_dump.h" namespace base { @@ -27,32 +24,6 @@ return std::string(kDumpRootName) + "/" + id.ToString(); } -// static -trace_event::MemoryAllocatorDumpGuid -SharedMemoryTracker::GetGlobalDumpIdForTracing(const UnguessableToken& id) { - std::string dump_name = GetDumpNameForTracing(id); - return trace_event::MemoryAllocatorDumpGuid(dump_name); -} - -// static -const trace_event::MemoryAllocatorDump* -SharedMemoryTracker::GetOrCreateSharedMemoryDump( - const SharedMemory* shared_memory, - trace_event::ProcessMemoryDump* pmd) { - return GetOrCreateSharedMemoryDumpInternal(shared_memory->memory(), - shared_memory->mapped_size(), - shared_memory->mapped_id(), pmd); -} - -const trace_event::MemoryAllocatorDump* -SharedMemoryTracker::GetOrCreateSharedMemoryDump( - const SharedMemoryMapping& shared_memory, - trace_event::ProcessMemoryDump* pmd) { - return GetOrCreateSharedMemoryDumpInternal(shared_memory.raw_memory_ptr(), - shared_memory.mapped_size(), - shared_memory.guid(), pmd); -} - void SharedMemoryTracker::IncrementMemoryUsage( const SharedMemory& shared_memory) { AutoLock hold(usages_lock_); @@ -84,64 +55,8 @@ } SharedMemoryTracker::SharedMemoryTracker() { - trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - this, "SharedMemoryTracker", nullptr); } SharedMemoryTracker::~SharedMemoryTracker() = default; -bool SharedMemoryTracker::OnMemoryDump(const trace_event::MemoryDumpArgs& args, - trace_event::ProcessMemoryDump* pmd) { - AutoLock hold(usages_lock_); - for (const auto& usage : usages_) { - const trace_event::MemoryAllocatorDump* dump = - GetOrCreateSharedMemoryDumpInternal( - usage.first, usage.second.mapped_size, usage.second.mapped_id, pmd); - DCHECK(dump); - } - return true; -} - -// static -const trace_event::MemoryAllocatorDump* -SharedMemoryTracker::GetOrCreateSharedMemoryDumpInternal( - void* mapped_memory, - size_t mapped_size, - const UnguessableToken& mapped_id, - trace_event::ProcessMemoryDump* pmd) { - const std::string dump_name = GetDumpNameForTracing(mapped_id); - trace_event::MemoryAllocatorDump* local_dump = - pmd->GetAllocatorDump(dump_name); - if (local_dump) - return local_dump; - - size_t virtual_size = mapped_size; - // If resident size is not available, a virtual size is used as fallback. - size_t size = virtual_size; -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) - base::Optional<size_t> resident_size = - trace_event::ProcessMemoryDump::CountResidentBytesInSharedMemory( - mapped_memory, mapped_size); - if (resident_size.has_value()) - size = resident_size.value(); -#endif - - local_dump = pmd->CreateAllocatorDump(dump_name); - local_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize, - trace_event::MemoryAllocatorDump::kUnitsBytes, size); - local_dump->AddScalar("virtual_size", - trace_event::MemoryAllocatorDump::kUnitsBytes, - virtual_size); - auto global_dump_guid = GetGlobalDumpIdForTracing(mapped_id); - trace_event::MemoryAllocatorDump* global_dump = - pmd->CreateSharedGlobalAllocatorDump(global_dump_guid); - global_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize, - trace_event::MemoryAllocatorDump::kUnitsBytes, size); - - // The edges will be overriden by the clients with correct importance. - pmd->AddOverridableOwnershipEdge(local_dump->guid(), global_dump->guid(), - 0 /* importance */); - return local_dump; -} - } // namespace
diff --git a/base/memory/shared_memory_tracker.h b/base/memory/shared_memory_tracker.h index 499b172..72c7b7a 100644 --- a/base/memory/shared_memory_tracker.h +++ b/base/memory/shared_memory_tracker.h
@@ -11,39 +11,17 @@ #include "base/memory/shared_memory.h" #include "base/memory/shared_memory_mapping.h" #include "base/synchronization/lock.h" -#include "base/trace_event/memory_dump_provider.h" namespace base { -namespace trace_event { -class MemoryAllocatorDump; -class MemoryAllocatorDumpGuid; -class ProcessMemoryDump; -} - // SharedMemoryTracker tracks shared memory usage. -class BASE_EXPORT SharedMemoryTracker : public trace_event::MemoryDumpProvider { +class BASE_EXPORT SharedMemoryTracker { public: // Returns a singleton instance. static SharedMemoryTracker* GetInstance(); static std::string GetDumpNameForTracing(const UnguessableToken& id); - static trace_event::MemoryAllocatorDumpGuid GetGlobalDumpIdForTracing( - const UnguessableToken& id); - - // Gets or creates if non-existant, a memory dump for the |shared_memory| - // inside the given |pmd|. Also adds the necessary edges for the dump when - // creating the dump. - static const trace_event::MemoryAllocatorDump* GetOrCreateSharedMemoryDump( - const SharedMemory* shared_memory, - trace_event::ProcessMemoryDump* pmd); - // We're in the middle of a refactor https://crbug.com/795291. Eventually, the - // first call will go away. - static const trace_event::MemoryAllocatorDump* GetOrCreateSharedMemoryDump( - const SharedMemoryMapping& shared_memory, - trace_event::ProcessMemoryDump* pmd); - // Records shared memory usage on valid mapping. void IncrementMemoryUsage(const SharedMemory& shared_memory); void IncrementMemoryUsage(const SharedMemoryMapping& mapping); @@ -57,17 +35,7 @@ private: SharedMemoryTracker(); - ~SharedMemoryTracker() override; - - // trace_event::MemoryDumpProvider implementation. - bool OnMemoryDump(const trace_event::MemoryDumpArgs& args, - trace_event::ProcessMemoryDump* pmd) override; - - static const trace_event::MemoryAllocatorDump* - GetOrCreateSharedMemoryDumpInternal(void* mapped_memory, - size_t mapped_size, - const UnguessableToken& mapped_id, - trace_event::ProcessMemoryDump* pmd); + ~SharedMemoryTracker(); // Information associated with each mapped address. struct UsageInfo {
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index a7c3f25..0953aaf 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc
@@ -18,7 +18,6 @@ #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_task_runner_handle.h" -#include "base/trace_event/trace_event.h" #if defined(OS_MACOSX) #include "base/message_loop/message_pump_mac.h" @@ -312,8 +311,6 @@ // Execute the task and assume the worst: It is probably not reentrant. task_execution_allowed_ = false; - TRACE_TASK_EXECUTION("MessageLoop::RunTask", *pending_task); - for (auto& observer : task_observers_) observer.WillProcessTask(*pending_task); incoming_task_queue_->RunTask(pending_task);
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc index a8efd27..2b47681 100644 --- a/base/message_loop/message_pump_libevent.cc +++ b/base/message_loop/message_pump_libevent.cc
@@ -16,7 +16,6 @@ #include "base/posix/eintr_wrapper.h" #include "base/third_party/libevent/event.h" #include "base/time/time.h" -#include "base/trace_event/trace_event.h" #include "build_config.h" #if defined(OS_MACOSX) @@ -306,11 +305,6 @@ void* context) { FdWatchController* controller = static_cast<FdWatchController*>(context); DCHECK(controller); - TRACE_EVENT2("toplevel", "MessagePumpLibevent::OnLibeventNotification", - "src_file", controller->created_from_location().file_name(), - "src_func", controller->created_from_location().function_name()); - TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION heap_profiler_scope( - controller->created_from_location().file_name()); MessagePumpLibevent* pump = controller->pump(); pump->processed_io_events_ = true;
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc index 8e6f1f4..47cf477 100644 --- a/base/message_loop/message_pump_win.cc +++ b/base/message_loop/message_pump_win.cc
@@ -13,7 +13,6 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event.h" #include "base/win/current_module.h" #include "base/win/wrapped_window_proc.h" @@ -347,8 +346,6 @@ } bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { - TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper", - "message", msg.message); if (WM_QUIT == msg.message) { // WM_QUIT is the standard way to exit a GetMessage() loop. Our MessageLoop // has its own quit mechanism, so WM_QUIT is unexpected and should be
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc index d1690bc..1004012 100644 --- a/base/process/launch_posix.cc +++ b/base/process/launch_posix.cc
@@ -42,7 +42,6 @@ #include "base/threading/platform_thread.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" -#include "base/trace_event/trace_event.h" #include "build_config.h" #if defined(OS_LINUX) || defined(OS_AIX)
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc index d3b8c0c..33b400a 100644 --- a/base/task_scheduler/scheduler_worker.cc +++ b/base/task_scheduler/scheduler_worker.cc
@@ -13,7 +13,6 @@ #include "base/logging.h" #include "base/task_scheduler/scheduler_worker_observer.h" #include "base/task_scheduler/task_tracker.h" -#include "base/trace_event/trace_event.h" #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" @@ -274,7 +273,6 @@ void SchedulerWorker::RunWorker() { DCHECK_EQ(self_, this); - TRACE_EVENT_BEGIN0("task_scheduler", "SchedulerWorkerThread active"); if (scheduler_worker_observer_) scheduler_worker_observer_->OnSchedulerWorkerMainEntry(); @@ -283,9 +281,7 @@ // A SchedulerWorker starts out waiting for work. { - TRACE_EVENT_END0("task_scheduler", "SchedulerWorkerThread active"); delegate_->WaitForWork(&wake_up_event_); - TRACE_EVENT_BEGIN0("task_scheduler", "SchedulerWorkerThread active"); } // When defined(COM_INIT_CHECK_HOOK_ENABLED), ignore @@ -311,9 +307,7 @@ if (ShouldExit()) break; - TRACE_EVENT_END0("task_scheduler", "SchedulerWorkerThread active"); delegate_->WaitForWork(&wake_up_event_); - TRACE_EVENT_BEGIN0("task_scheduler", "SchedulerWorkerThread active"); continue; } @@ -345,8 +339,6 @@ // Release the self-reference to |this|. This can result in deleting |this| // and as such no more member accesses should be made after this point. self_ = nullptr; - - TRACE_EVENT_END0("task_scheduler", "SchedulerWorkerThread active"); } } // namespace internal
diff --git a/base/task_scheduler/task_tracker.cc b/base/task_scheduler/task_tracker.cc index 5c98b5c..4fd2356 100644 --- a/base/task_scheduler/task_tracker.cc +++ b/base/task_scheduler/task_tracker.cc
@@ -15,6 +15,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/sequence_token.h" +#include "base/strings/string_util.h" #include "base/synchronization/condition_variable.h" #include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h" #include "base/threading/sequence_local_storage_map.h" @@ -22,7 +23,6 @@ #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "base/trace_event/trace_event.h" #include "base/values.h" namespace base { @@ -35,7 +35,7 @@ constexpr char kSingleThreadExecutionMode[] = "single thread"; // An immutable copy of a scheduler task's info required by tracing. -class TaskTracingInfo : public trace_event::ConvertableToTraceFormat { +class TaskTracingInfo { public: TaskTracingInfo(const TaskTraits& task_traits, const char* execution_mode, @@ -44,9 +44,6 @@ execution_mode_(execution_mode), sequence_token_(sequence_token) {} - // trace_event::ConvertableToTraceFormat implementation. - void AppendAsTraceFormat(std::string* out) const override; - private: const TaskTraits task_traits_; const char* const execution_mode_; @@ -55,28 +52,11 @@ DISALLOW_COPY_AND_ASSIGN(TaskTracingInfo); }; -void TaskTracingInfo::AppendAsTraceFormat(std::string* out) const { - DictionaryValue dict; - - dict.SetString("task_priority", - base::TaskPriorityToString(task_traits_.priority())); - dict.SetString("execution_mode", execution_mode_); - if (execution_mode_ != kParallelExecutionMode) - dict.SetInteger("sequence_token", sequence_token_.ToInternalValue()); - - std::string tmp; - JSONWriter::Write(dict, &tmp); - out->append(tmp); -} - // These name conveys that a Task is posted to/run by the task scheduler without // revealing its implementation details. constexpr char kQueueFunctionName[] = "TaskScheduler PostTask"; constexpr char kRunFunctionName[] = "TaskScheduler RunTask"; -constexpr char kTaskSchedulerFlowTracingCategory[] = - TRACE_DISABLED_BY_DEFAULT("task_scheduler.flow"); - // Constructs a histogram to track latency which is logging to // "TaskScheduler.{histogram_name}.{histogram_label}.{task_type_suffix}". HistogramBase* GetLatencyHistogram(StringPiece histogram_name, @@ -347,13 +327,6 @@ if (task.delayed_run_time.is_null()) subtle::NoBarrier_AtomicIncrement(&num_incomplete_undelayed_tasks_, 1); - { - TRACE_EVENT_WITH_FLOW0( - kTaskSchedulerFlowTracingCategory, kQueueFunctionName, - TRACE_ID_MANGLE(task_annotator_.GetTaskTraceID(task)), - TRACE_EVENT_FLAG_FLOW_OUT); - } - task_annotator_.DidQueueTask(nullptr, task); return true; @@ -496,29 +469,6 @@ } if (can_run_task) { - TRACE_TASK_EXECUTION(kRunFunctionName, task); - - const char* const execution_mode = - task.single_thread_task_runner_ref - ? kSingleThreadExecutionMode - : (task.sequenced_task_runner_ref ? kSequencedExecutionMode - : kParallelExecutionMode); - // TODO(gab): In a better world this would be tacked on as an extra arg - // to the trace event generated above. This is not possible however until - // http://crbug.com/652692 is resolved. - TRACE_EVENT1("task_scheduler", "TaskTracker::RunTask", "task_info", - std::make_unique<TaskTracingInfo>( - task.traits, execution_mode, sequence_token)); - - { - // Put this in its own scope so it preceeds rather than overlaps with - // RunTask() in the trace view. - TRACE_EVENT_WITH_FLOW0( - kTaskSchedulerFlowTracingCategory, kQueueFunctionName, - TRACE_ID_MANGLE(task_annotator_.GetTaskTraceID(task)), - TRACE_EVENT_FLAG_FLOW_IN); - } - task_annotator_.RunTask(nullptr, &task); }
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h index 23dbb2f..993db05 100644 --- a/base/test/test_mock_time_task_runner.h +++ b/base/test/test_mock_time_task_runner.h
@@ -17,6 +17,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "base/test/test_pending_task.h" #include "base/threading/thread_checker_impl.h"
diff --git a/base/test/test_pending_task.cc b/base/test/test_pending_task.cc index f9cfa8e..bb81eaa 100644 --- a/base/test/test_pending_task.cc +++ b/base/test/test_pending_task.cc
@@ -38,44 +38,4 @@ TestPendingTask::~TestPendingTask() = default; -void TestPendingTask::AsValueInto(base::trace_event::TracedValue* state) const { - state->SetInteger("run_at", GetTimeToRun().ToInternalValue()); - state->SetString("posting_function", location.ToString()); - state->SetInteger("post_time", post_time.ToInternalValue()); - state->SetInteger("delay", delay.ToInternalValue()); - switch (nestability) { - case NESTABLE: - state->SetString("nestability", "NESTABLE"); - break; - case NON_NESTABLE: - state->SetString("nestability", "NON_NESTABLE"); - break; - } - state->SetInteger("delay", delay.ToInternalValue()); -} - -std::unique_ptr<base::trace_event::ConvertableToTraceFormat> -TestPendingTask::AsValue() const { - std::unique_ptr<base::trace_event::TracedValue> state( - new base::trace_event::TracedValue()); - AsValueInto(state.get()); - return std::move(state); -} - -std::string TestPendingTask::ToString() const { - std::string output("TestPendingTask("); - AsValue()->AppendAsTraceFormat(&output); - output += ")"; - return output; -} - -std::ostream& operator<<(std::ostream& os, const TestPendingTask& task) { - PrintTo(task, &os); - return os; -} - -void PrintTo(const TestPendingTask& task, std::ostream* os) { - *os << task.ToString(); -} - } // namespace base
diff --git a/base/test/test_pending_task.h b/base/test/test_pending_task.h index 460de0e..5e607ac 100644 --- a/base/test/test_pending_task.h +++ b/base/test/test_pending_task.h
@@ -10,7 +10,6 @@ #include "base/callback.h" #include "base/location.h" #include "base/time/time.h" -#include "base/trace_event/trace_event_argument.h" namespace base { @@ -58,21 +57,10 @@ TimeDelta delay; TestNestability nestability; - // Functions for using test pending task with tracing, useful in unit - // testing. - void AsValueInto(base::trace_event::TracedValue* state) const; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const; - std::string ToString() const; - private: DISALLOW_COPY_AND_ASSIGN(TestPendingTask); }; -// gtest helpers which allow pretty printing of the tasks, very useful in unit -// testing. -std::ostream& operator<<(std::ostream& os, const TestPendingTask& task); -void PrintTo(const TestPendingTask& task, std::ostream* os); - } // namespace base #endif // BASE_TEST_TEST_PENDING_TASK_H_
diff --git a/base/test/trace_event_analyzer.cc b/base/test/trace_event_analyzer.cc deleted file mode 100644 index cab2899..0000000 --- a/base/test/trace_event_analyzer.cc +++ /dev/null
@@ -1,1069 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/test/trace_event_analyzer.h" - -#include <math.h> - -#include <algorithm> -#include <set> - -#include "base/json/json_reader.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted_memory.h" -#include "base/run_loop.h" -#include "base/strings/pattern.h" -#include "base/trace_event/trace_buffer.h" -#include "base/trace_event/trace_config.h" -#include "base/trace_event/trace_log.h" -#include "base/values.h" - -namespace { -void OnTraceDataCollected(base::OnceClosure quit_closure, - base::trace_event::TraceResultBuffer* buffer, - const scoped_refptr<base::RefCountedString>& json, - bool has_more_events) { - buffer->AddFragment(json->data()); - if (!has_more_events) - std::move(quit_closure).Run(); -} -} // namespace - -namespace trace_analyzer { - -// TraceEvent - -TraceEvent::TraceEvent() - : thread(0, 0), - timestamp(0), - duration(0), - phase(TRACE_EVENT_PHASE_BEGIN), - other_event(nullptr) {} - -TraceEvent::TraceEvent(TraceEvent&& other) = default; - -TraceEvent::~TraceEvent() = default; - -TraceEvent& TraceEvent::operator=(TraceEvent&& rhs) = default; - -bool TraceEvent::SetFromJSON(const base::Value* event_value) { - if (event_value->type() != base::Value::Type::DICTIONARY) { - LOG(ERROR) << "Value must be Type::DICTIONARY"; - return false; - } - const base::DictionaryValue* dictionary = - static_cast<const base::DictionaryValue*>(event_value); - - std::string phase_str; - const base::DictionaryValue* args = nullptr; - - if (!dictionary->GetString("ph", &phase_str)) { - LOG(ERROR) << "ph is missing from TraceEvent JSON"; - return false; - } - - phase = *phase_str.data(); - - bool may_have_duration = (phase == TRACE_EVENT_PHASE_COMPLETE); - bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA); - bool require_id = (phase == TRACE_EVENT_PHASE_ASYNC_BEGIN || - phase == TRACE_EVENT_PHASE_ASYNC_STEP_INTO || - phase == TRACE_EVENT_PHASE_ASYNC_STEP_PAST || - phase == TRACE_EVENT_PHASE_MEMORY_DUMP || - phase == TRACE_EVENT_PHASE_ENTER_CONTEXT || - phase == TRACE_EVENT_PHASE_LEAVE_CONTEXT || - phase == TRACE_EVENT_PHASE_CREATE_OBJECT || - phase == TRACE_EVENT_PHASE_DELETE_OBJECT || - phase == TRACE_EVENT_PHASE_SNAPSHOT_OBJECT || - phase == TRACE_EVENT_PHASE_ASYNC_END); - - if (require_origin && !dictionary->GetInteger("pid", &thread.process_id)) { - LOG(ERROR) << "pid is missing from TraceEvent JSON"; - return false; - } - if (require_origin && !dictionary->GetInteger("tid", &thread.thread_id)) { - LOG(ERROR) << "tid is missing from TraceEvent JSON"; - return false; - } - if (require_origin && !dictionary->GetDouble("ts", ×tamp)) { - LOG(ERROR) << "ts is missing from TraceEvent JSON"; - return false; - } - if (may_have_duration) { - dictionary->GetDouble("dur", &duration); - } - if (!dictionary->GetString("cat", &category)) { - LOG(ERROR) << "cat is missing from TraceEvent JSON"; - return false; - } - if (!dictionary->GetString("name", &name)) { - LOG(ERROR) << "name is missing from TraceEvent JSON"; - return false; - } - if (!dictionary->GetDictionary("args", &args)) { - LOG(ERROR) << "args is missing from TraceEvent JSON"; - return false; - } - if (require_id && !dictionary->GetString("id", &id)) { - LOG(ERROR) << "id is missing from ASYNC_BEGIN/ASYNC_END TraceEvent JSON"; - return false; - } - - dictionary->GetDouble("tdur", &thread_duration); - dictionary->GetDouble("tts", &thread_timestamp); - dictionary->GetString("scope", &scope); - dictionary->GetString("bind_id", &bind_id); - dictionary->GetBoolean("flow_out", &flow_out); - dictionary->GetBoolean("flow_in", &flow_in); - - const base::DictionaryValue* id2; - if (dictionary->GetDictionary("id2", &id2)) { - id2->GetString("global", &global_id2); - id2->GetString("local", &local_id2); - } - - // For each argument, copy the type and create a trace_analyzer::TraceValue. - for (base::DictionaryValue::Iterator it(*args); !it.IsAtEnd(); - it.Advance()) { - std::string str; - bool boolean = false; - int int_num = 0; - double double_num = 0.0; - if (it.value().GetAsString(&str)) { - arg_strings[it.key()] = str; - } else if (it.value().GetAsInteger(&int_num)) { - arg_numbers[it.key()] = static_cast<double>(int_num); - } else if (it.value().GetAsBoolean(&boolean)) { - arg_numbers[it.key()] = static_cast<double>(boolean ? 1 : 0); - } else if (it.value().GetAsDouble(&double_num)) { - arg_numbers[it.key()] = double_num; - } - // Record all arguments as values. - arg_values[it.key()] = it.value().CreateDeepCopy(); - } - - return true; -} - -double TraceEvent::GetAbsTimeToOtherEvent() const { - return fabs(other_event->timestamp - timestamp); -} - -bool TraceEvent::GetArgAsString(const std::string& name, - std::string* arg) const { - const auto it = arg_strings.find(name); - if (it != arg_strings.end()) { - *arg = it->second; - return true; - } - return false; -} - -bool TraceEvent::GetArgAsNumber(const std::string& name, - double* arg) const { - const auto it = arg_numbers.find(name); - if (it != arg_numbers.end()) { - *arg = it->second; - return true; - } - return false; -} - -bool TraceEvent::GetArgAsValue(const std::string& name, - std::unique_ptr<base::Value>* arg) const { - const auto it = arg_values.find(name); - if (it != arg_values.end()) { - *arg = it->second->CreateDeepCopy(); - return true; - } - return false; -} - -bool TraceEvent::HasStringArg(const std::string& name) const { - return (arg_strings.find(name) != arg_strings.end()); -} - -bool TraceEvent::HasNumberArg(const std::string& name) const { - return (arg_numbers.find(name) != arg_numbers.end()); -} - -bool TraceEvent::HasArg(const std::string& name) const { - return (arg_values.find(name) != arg_values.end()); -} - -std::string TraceEvent::GetKnownArgAsString(const std::string& name) const { - std::string arg_string; - bool result = GetArgAsString(name, &arg_string); - DCHECK(result); - return arg_string; -} - -double TraceEvent::GetKnownArgAsDouble(const std::string& name) const { - double arg_double = 0; - bool result = GetArgAsNumber(name, &arg_double); - DCHECK(result); - return arg_double; -} - -int TraceEvent::GetKnownArgAsInt(const std::string& name) const { - double arg_double = 0; - bool result = GetArgAsNumber(name, &arg_double); - DCHECK(result); - return static_cast<int>(arg_double); -} - -bool TraceEvent::GetKnownArgAsBool(const std::string& name) const { - double arg_double = 0; - bool result = GetArgAsNumber(name, &arg_double); - DCHECK(result); - return (arg_double != 0.0); -} - -std::unique_ptr<base::Value> TraceEvent::GetKnownArgAsValue( - const std::string& name) const { - std::unique_ptr<base::Value> arg_value; - bool result = GetArgAsValue(name, &arg_value); - DCHECK(result); - return arg_value; -} - -// QueryNode - -QueryNode::QueryNode(const Query& query) : query_(query) { -} - -QueryNode::~QueryNode() = default; - -// Query - -Query::Query(TraceEventMember member) - : type_(QUERY_EVENT_MEMBER), - operator_(OP_INVALID), - member_(member), - number_(0), - is_pattern_(false) { -} - -Query::Query(TraceEventMember member, const std::string& arg_name) - : type_(QUERY_EVENT_MEMBER), - operator_(OP_INVALID), - member_(member), - number_(0), - string_(arg_name), - is_pattern_(false) { -} - -Query::Query(const Query& query) = default; - -Query::~Query() = default; - -Query Query::String(const std::string& str) { - return Query(str); -} - -Query Query::Double(double num) { - return Query(num); -} - -Query Query::Int(int32_t num) { - return Query(static_cast<double>(num)); -} - -Query Query::Uint(uint32_t num) { - return Query(static_cast<double>(num)); -} - -Query Query::Bool(bool boolean) { - return Query(boolean ? 1.0 : 0.0); -} - -Query Query::Phase(char phase) { - return Query(static_cast<double>(phase)); -} - -Query Query::Pattern(const std::string& pattern) { - Query query(pattern); - query.is_pattern_ = true; - return query; -} - -bool Query::Evaluate(const TraceEvent& event) const { - // First check for values that can convert to bool. - - // double is true if != 0: - double bool_value = 0.0; - bool is_bool = GetAsDouble(event, &bool_value); - if (is_bool) - return (bool_value != 0.0); - - // string is true if it is non-empty: - std::string str_value; - bool is_str = GetAsString(event, &str_value); - if (is_str) - return !str_value.empty(); - - DCHECK_EQ(QUERY_BOOLEAN_OPERATOR, type_) - << "Invalid query: missing boolean expression"; - DCHECK(left_.get()); - DCHECK(right_.get() || is_unary_operator()); - - if (is_comparison_operator()) { - DCHECK(left().is_value() && right().is_value()) - << "Invalid query: comparison operator used between event member and " - "value."; - bool compare_result = false; - if (CompareAsDouble(event, &compare_result)) - return compare_result; - if (CompareAsString(event, &compare_result)) - return compare_result; - return false; - } - // It's a logical operator. - switch (operator_) { - case OP_AND: - return left().Evaluate(event) && right().Evaluate(event); - case OP_OR: - return left().Evaluate(event) || right().Evaluate(event); - case OP_NOT: - return !left().Evaluate(event); - default: - NOTREACHED(); - return false; - } -} - -bool Query::CompareAsDouble(const TraceEvent& event, bool* result) const { - double lhs, rhs; - if (!left().GetAsDouble(event, &lhs) || !right().GetAsDouble(event, &rhs)) - return false; - switch (operator_) { - case OP_EQ: - *result = (lhs == rhs); - return true; - case OP_NE: - *result = (lhs != rhs); - return true; - case OP_LT: - *result = (lhs < rhs); - return true; - case OP_LE: - *result = (lhs <= rhs); - return true; - case OP_GT: - *result = (lhs > rhs); - return true; - case OP_GE: - *result = (lhs >= rhs); - return true; - default: - NOTREACHED(); - return false; - } -} - -bool Query::CompareAsString(const TraceEvent& event, bool* result) const { - std::string lhs, rhs; - if (!left().GetAsString(event, &lhs) || !right().GetAsString(event, &rhs)) - return false; - switch (operator_) { - case OP_EQ: - if (right().is_pattern_) - *result = base::MatchPattern(lhs, rhs); - else if (left().is_pattern_) - *result = base::MatchPattern(rhs, lhs); - else - *result = (lhs == rhs); - return true; - case OP_NE: - if (right().is_pattern_) - *result = !base::MatchPattern(lhs, rhs); - else if (left().is_pattern_) - *result = !base::MatchPattern(rhs, lhs); - else - *result = (lhs != rhs); - return true; - case OP_LT: - *result = (lhs < rhs); - return true; - case OP_LE: - *result = (lhs <= rhs); - return true; - case OP_GT: - *result = (lhs > rhs); - return true; - case OP_GE: - *result = (lhs >= rhs); - return true; - default: - NOTREACHED(); - return false; - } -} - -bool Query::EvaluateArithmeticOperator(const TraceEvent& event, - double* num) const { - DCHECK_EQ(QUERY_ARITHMETIC_OPERATOR, type_); - DCHECK(left_.get()); - DCHECK(right_.get() || is_unary_operator()); - - double lhs = 0, rhs = 0; - if (!left().GetAsDouble(event, &lhs)) - return false; - if (!is_unary_operator() && !right().GetAsDouble(event, &rhs)) - return false; - - switch (operator_) { - case OP_ADD: - *num = lhs + rhs; - return true; - case OP_SUB: - *num = lhs - rhs; - return true; - case OP_MUL: - *num = lhs * rhs; - return true; - case OP_DIV: - *num = lhs / rhs; - return true; - case OP_MOD: - *num = static_cast<double>(static_cast<int64_t>(lhs) % - static_cast<int64_t>(rhs)); - return true; - case OP_NEGATE: - *num = -lhs; - return true; - default: - NOTREACHED(); - return false; - } -} - -bool Query::GetAsDouble(const TraceEvent& event, double* num) const { - switch (type_) { - case QUERY_ARITHMETIC_OPERATOR: - return EvaluateArithmeticOperator(event, num); - case QUERY_EVENT_MEMBER: - return GetMemberValueAsDouble(event, num); - case QUERY_NUMBER: - *num = number_; - return true; - default: - return false; - } -} - -bool Query::GetAsString(const TraceEvent& event, std::string* str) const { - switch (type_) { - case QUERY_EVENT_MEMBER: - return GetMemberValueAsString(event, str); - case QUERY_STRING: - *str = string_; - return true; - default: - return false; - } -} - -const TraceEvent* Query::SelectTargetEvent(const TraceEvent* event, - TraceEventMember member) { - if (member >= OTHER_FIRST_MEMBER && member <= OTHER_LAST_MEMBER) { - return event->other_event; - } else if (member >= PREV_FIRST_MEMBER && member <= PREV_LAST_MEMBER) { - return event->prev_event; - } else { - return event; - } -} - -bool Query::GetMemberValueAsDouble(const TraceEvent& event, - double* num) const { - DCHECK_EQ(QUERY_EVENT_MEMBER, type_); - - // This could be a request for a member of |event| or a member of |event|'s - // associated previous or next event. Store the target event in the_event: - const TraceEvent* the_event = SelectTargetEvent(&event, member_); - - // Request for member of associated event, but there is no associated event. - if (!the_event) - return false; - - switch (member_) { - case EVENT_PID: - case OTHER_PID: - case PREV_PID: - *num = static_cast<double>(the_event->thread.process_id); - return true; - case EVENT_TID: - case OTHER_TID: - case PREV_TID: - *num = static_cast<double>(the_event->thread.thread_id); - return true; - case EVENT_TIME: - case OTHER_TIME: - case PREV_TIME: - *num = the_event->timestamp; - return true; - case EVENT_DURATION: - if (!the_event->has_other_event()) - return false; - *num = the_event->GetAbsTimeToOtherEvent(); - return true; - case EVENT_COMPLETE_DURATION: - if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE) - return false; - *num = the_event->duration; - return true; - case EVENT_PHASE: - case OTHER_PHASE: - case PREV_PHASE: - *num = static_cast<double>(the_event->phase); - return true; - case EVENT_HAS_STRING_ARG: - case OTHER_HAS_STRING_ARG: - case PREV_HAS_STRING_ARG: - *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0); - return true; - case EVENT_HAS_NUMBER_ARG: - case OTHER_HAS_NUMBER_ARG: - case PREV_HAS_NUMBER_ARG: - *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0); - return true; - case EVENT_ARG: - case OTHER_ARG: - case PREV_ARG: { - // Search for the argument name and return its value if found. - std::map<std::string, double>::const_iterator num_i = - the_event->arg_numbers.find(string_); - if (num_i == the_event->arg_numbers.end()) - return false; - *num = num_i->second; - return true; - } - case EVENT_HAS_OTHER: - // return 1.0 (true) if the other event exists - *num = event.other_event ? 1.0 : 0.0; - return true; - case EVENT_HAS_PREV: - *num = event.prev_event ? 1.0 : 0.0; - return true; - default: - return false; - } -} - -bool Query::GetMemberValueAsString(const TraceEvent& event, - std::string* str) const { - DCHECK_EQ(QUERY_EVENT_MEMBER, type_); - - // This could be a request for a member of |event| or a member of |event|'s - // associated previous or next event. Store the target event in the_event: - const TraceEvent* the_event = SelectTargetEvent(&event, member_); - - // Request for member of associated event, but there is no associated event. - if (!the_event) - return false; - - switch (member_) { - case EVENT_CATEGORY: - case OTHER_CATEGORY: - case PREV_CATEGORY: - *str = the_event->category; - return true; - case EVENT_NAME: - case OTHER_NAME: - case PREV_NAME: - *str = the_event->name; - return true; - case EVENT_ID: - case OTHER_ID: - case PREV_ID: - *str = the_event->id; - return true; - case EVENT_ARG: - case OTHER_ARG: - case PREV_ARG: { - // Search for the argument name and return its value if found. - std::map<std::string, std::string>::const_iterator str_i = - the_event->arg_strings.find(string_); - if (str_i == the_event->arg_strings.end()) - return false; - *str = str_i->second; - return true; - } - default: - return false; - } -} - -Query::Query(const std::string& str) - : type_(QUERY_STRING), - operator_(OP_INVALID), - member_(EVENT_INVALID), - number_(0), - string_(str), - is_pattern_(false) { -} - -Query::Query(double num) - : type_(QUERY_NUMBER), - operator_(OP_INVALID), - member_(EVENT_INVALID), - number_(num), - is_pattern_(false) { -} -const Query& Query::left() const { - return left_->query(); -} - -const Query& Query::right() const { - return right_->query(); -} - -Query Query::operator==(const Query& rhs) const { - return Query(*this, rhs, OP_EQ); -} - -Query Query::operator!=(const Query& rhs) const { - return Query(*this, rhs, OP_NE); -} - -Query Query::operator<(const Query& rhs) const { - return Query(*this, rhs, OP_LT); -} - -Query Query::operator<=(const Query& rhs) const { - return Query(*this, rhs, OP_LE); -} - -Query Query::operator>(const Query& rhs) const { - return Query(*this, rhs, OP_GT); -} - -Query Query::operator>=(const Query& rhs) const { - return Query(*this, rhs, OP_GE); -} - -Query Query::operator&&(const Query& rhs) const { - return Query(*this, rhs, OP_AND); -} - -Query Query::operator||(const Query& rhs) const { - return Query(*this, rhs, OP_OR); -} - -Query Query::operator!() const { - return Query(*this, OP_NOT); -} - -Query Query::operator+(const Query& rhs) const { - return Query(*this, rhs, OP_ADD); -} - -Query Query::operator-(const Query& rhs) const { - return Query(*this, rhs, OP_SUB); -} - -Query Query::operator*(const Query& rhs) const { - return Query(*this, rhs, OP_MUL); -} - -Query Query::operator/(const Query& rhs) const { - return Query(*this, rhs, OP_DIV); -} - -Query Query::operator%(const Query& rhs) const { - return Query(*this, rhs, OP_MOD); -} - -Query Query::operator-() const { - return Query(*this, OP_NEGATE); -} - - -Query::Query(const Query& left, const Query& right, Operator binary_op) - : operator_(binary_op), - left_(new QueryNode(left)), - right_(new QueryNode(right)), - member_(EVENT_INVALID), - number_(0) { - type_ = (binary_op < OP_ADD ? - QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR); -} - -Query::Query(const Query& left, Operator unary_op) - : operator_(unary_op), - left_(new QueryNode(left)), - member_(EVENT_INVALID), - number_(0) { - type_ = (unary_op < OP_ADD ? - QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR); -} - -namespace { - -// Search |events| for |query| and add matches to |output|. -size_t FindMatchingEvents(const std::vector<TraceEvent>& events, - const Query& query, - TraceEventVector* output, - bool ignore_metadata_events) { - for (size_t i = 0; i < events.size(); ++i) { - if (ignore_metadata_events && events[i].phase == TRACE_EVENT_PHASE_METADATA) - continue; - if (query.Evaluate(events[i])) - output->push_back(&events[i]); - } - return output->size(); -} - -bool ParseEventsFromJson(const std::string& json, - std::vector<TraceEvent>* output) { - std::unique_ptr<base::Value> root = base::JSONReader::Read(json); - - base::ListValue* root_list = nullptr; - if (!root.get() || !root->GetAsList(&root_list)) - return false; - - for (size_t i = 0; i < root_list->GetSize(); ++i) { - base::Value* item = nullptr; - if (root_list->Get(i, &item)) { - TraceEvent event; - if (event.SetFromJSON(item)) - output->push_back(std::move(event)); - else - return false; - } - } - - return true; -} - -} // namespace - -// TraceAnalyzer - -TraceAnalyzer::TraceAnalyzer() - : ignore_metadata_events_(false), allow_association_changes_(true) {} - -TraceAnalyzer::~TraceAnalyzer() = default; - -// static -TraceAnalyzer* TraceAnalyzer::Create(const std::string& json_events) { - std::unique_ptr<TraceAnalyzer> analyzer(new TraceAnalyzer()); - if (analyzer->SetEvents(json_events)) - return analyzer.release(); - return nullptr; -} - -bool TraceAnalyzer::SetEvents(const std::string& json_events) { - raw_events_.clear(); - if (!ParseEventsFromJson(json_events, &raw_events_)) - return false; - std::stable_sort(raw_events_.begin(), raw_events_.end()); - ParseMetadata(); - return true; -} - -void TraceAnalyzer::AssociateBeginEndEvents() { - using trace_analyzer::Query; - - Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN)); - Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END)); - Query match(Query::EventName() == Query::OtherName() && - Query::EventCategory() == Query::OtherCategory() && - Query::EventTid() == Query::OtherTid() && - Query::EventPid() == Query::OtherPid()); - - AssociateEvents(begin, end, match); -} - -void TraceAnalyzer::AssociateAsyncBeginEndEvents(bool match_pid) { - using trace_analyzer::Query; - - Query begin( - Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) || - Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) || - Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST)); - Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) || - Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) || - Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST)); - Query match(Query::EventCategory() == Query::OtherCategory() && - Query::EventId() == Query::OtherId()); - - if (match_pid) { - match = match && Query::EventPid() == Query::OtherPid(); - } - - AssociateEvents(begin, end, match); -} - -void TraceAnalyzer::AssociateEvents(const Query& first, - const Query& second, - const Query& match) { - DCHECK(allow_association_changes_) - << "AssociateEvents not allowed after FindEvents"; - - // Search for matching begin/end event pairs. When a matching end is found, - // it is associated with the begin event. - std::vector<TraceEvent*> begin_stack; - for (size_t event_index = 0; event_index < raw_events_.size(); - ++event_index) { - - TraceEvent& this_event = raw_events_[event_index]; - - if (second.Evaluate(this_event)) { - // Search stack for matching begin, starting from end. - for (int stack_index = static_cast<int>(begin_stack.size()) - 1; - stack_index >= 0; --stack_index) { - TraceEvent& begin_event = *begin_stack[stack_index]; - - // Temporarily set other to test against the match query. - const TraceEvent* other_backup = begin_event.other_event; - begin_event.other_event = &this_event; - if (match.Evaluate(begin_event)) { - // Found a matching begin/end pair. - // Set the associated previous event - this_event.prev_event = &begin_event; - // Erase the matching begin event index from the stack. - begin_stack.erase(begin_stack.begin() + stack_index); - break; - } - - // Not a match, restore original other and continue. - begin_event.other_event = other_backup; - } - } - // Even if this_event is a |second| event that has matched an earlier - // |first| event, it can still also be a |first| event and be associated - // with a later |second| event. - if (first.Evaluate(this_event)) { - begin_stack.push_back(&this_event); - } - } -} - -void TraceAnalyzer::MergeAssociatedEventArgs() { - for (size_t i = 0; i < raw_events_.size(); ++i) { - // Merge all associated events with the first event. - const TraceEvent* other = raw_events_[i].other_event; - // Avoid looping by keeping set of encountered TraceEvents. - std::set<const TraceEvent*> encounters; - encounters.insert(&raw_events_[i]); - while (other && encounters.find(other) == encounters.end()) { - encounters.insert(other); - raw_events_[i].arg_numbers.insert( - other->arg_numbers.begin(), - other->arg_numbers.end()); - raw_events_[i].arg_strings.insert( - other->arg_strings.begin(), - other->arg_strings.end()); - other = other->other_event; - } - } -} - -size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) { - allow_association_changes_ = false; - output->clear(); - return FindMatchingEvents( - raw_events_, query, output, ignore_metadata_events_); -} - -const TraceEvent* TraceAnalyzer::FindFirstOf(const Query& query) { - TraceEventVector output; - if (FindEvents(query, &output) > 0) - return output.front(); - return nullptr; -} - -const TraceEvent* TraceAnalyzer::FindLastOf(const Query& query) { - TraceEventVector output; - if (FindEvents(query, &output) > 0) - return output.back(); - return nullptr; -} - -const std::string& TraceAnalyzer::GetThreadName( - const TraceEvent::ProcessThreadID& thread) { - // If thread is not found, just add and return empty string. - return thread_names_[thread]; -} - -void TraceAnalyzer::ParseMetadata() { - for (size_t i = 0; i < raw_events_.size(); ++i) { - TraceEvent& this_event = raw_events_[i]; - // Check for thread name metadata. - if (this_event.phase != TRACE_EVENT_PHASE_METADATA || - this_event.name != "thread_name") - continue; - std::map<std::string, std::string>::const_iterator string_it = - this_event.arg_strings.find("name"); - if (string_it != this_event.arg_strings.end()) - thread_names_[this_event.thread] = string_it->second; - } -} - -// Utility functions for collecting process-local traces and creating a -// |TraceAnalyzer| from the result. - -void Start(const std::string& category_filter_string) { - DCHECK(!base::trace_event::TraceLog::GetInstance()->IsEnabled()); - base::trace_event::TraceLog::GetInstance()->SetEnabled( - base::trace_event::TraceConfig(category_filter_string, ""), - base::trace_event::TraceLog::RECORDING_MODE); -} - -std::unique_ptr<TraceAnalyzer> Stop() { - DCHECK(base::trace_event::TraceLog::GetInstance()->IsEnabled()); - base::trace_event::TraceLog::GetInstance()->SetDisabled(); - - base::trace_event::TraceResultBuffer buffer; - base::trace_event::TraceResultBuffer::SimpleOutput trace_output; - buffer.SetOutputCallback(trace_output.GetCallback()); - base::RunLoop run_loop; - buffer.Start(); - base::trace_event::TraceLog::GetInstance()->Flush( - base::BindRepeating(&OnTraceDataCollected, run_loop.QuitClosure(), - base::Unretained(&buffer))); - run_loop.Run(); - buffer.Finish(); - - return base::WrapUnique(TraceAnalyzer::Create(trace_output.json_output)); -} - -// TraceEventVector utility functions. - -bool GetRateStats(const TraceEventVector& events, - RateStats* stats, - const RateStatsOptions* options) { - DCHECK(stats); - // Need at least 3 events to calculate rate stats. - const size_t kMinEvents = 3; - if (events.size() < kMinEvents) { - LOG(ERROR) << "Not enough events: " << events.size(); - return false; - } - - std::vector<double> deltas; - size_t num_deltas = events.size() - 1; - for (size_t i = 0; i < num_deltas; ++i) { - double delta = events.at(i + 1)->timestamp - events.at(i)->timestamp; - if (delta < 0.0) { - LOG(ERROR) << "Events are out of order"; - return false; - } - deltas.push_back(delta); - } - - std::sort(deltas.begin(), deltas.end()); - - if (options) { - if (options->trim_min + options->trim_max > events.size() - kMinEvents) { - LOG(ERROR) << "Attempt to trim too many events"; - return false; - } - deltas.erase(deltas.begin(), deltas.begin() + options->trim_min); - deltas.erase(deltas.end() - options->trim_max, deltas.end()); - } - - num_deltas = deltas.size(); - double delta_sum = 0.0; - for (size_t i = 0; i < num_deltas; ++i) - delta_sum += deltas[i]; - - stats->min_us = *std::min_element(deltas.begin(), deltas.end()); - stats->max_us = *std::max_element(deltas.begin(), deltas.end()); - stats->mean_us = delta_sum / static_cast<double>(num_deltas); - - double sum_mean_offsets_squared = 0.0; - for (size_t i = 0; i < num_deltas; ++i) { - double offset = fabs(deltas[i] - stats->mean_us); - sum_mean_offsets_squared += offset * offset; - } - stats->standard_deviation_us = - sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1)); - - return true; -} - -bool FindFirstOf(const TraceEventVector& events, - const Query& query, - size_t position, - size_t* return_index) { - DCHECK(return_index); - for (size_t i = position; i < events.size(); ++i) { - if (query.Evaluate(*events[i])) { - *return_index = i; - return true; - } - } - return false; -} - -bool FindLastOf(const TraceEventVector& events, - const Query& query, - size_t position, - size_t* return_index) { - DCHECK(return_index); - for (size_t i = std::min(position + 1, events.size()); i != 0; --i) { - if (query.Evaluate(*events[i - 1])) { - *return_index = i - 1; - return true; - } - } - return false; -} - -bool FindClosest(const TraceEventVector& events, - const Query& query, - size_t position, - size_t* return_closest, - size_t* return_second_closest) { - DCHECK(return_closest); - if (events.empty() || position >= events.size()) - return false; - size_t closest = events.size(); - size_t second_closest = events.size(); - for (size_t i = 0; i < events.size(); ++i) { - if (!query.Evaluate(*events.at(i))) - continue; - if (closest == events.size()) { - closest = i; - continue; - } - if (fabs(events.at(i)->timestamp - events.at(position)->timestamp) < - fabs(events.at(closest)->timestamp - events.at(position)->timestamp)) { - second_closest = closest; - closest = i; - } else if (second_closest == events.size()) { - second_closest = i; - } - } - - if (closest < events.size() && - (!return_second_closest || second_closest < events.size())) { - *return_closest = closest; - if (return_second_closest) - *return_second_closest = second_closest; - return true; - } - - return false; -} - -size_t CountMatches(const TraceEventVector& events, - const Query& query, - size_t begin_position, - size_t end_position) { - if (begin_position >= events.size()) - return 0u; - end_position = (end_position < events.size()) ? end_position : events.size(); - size_t count = 0u; - for (size_t i = begin_position; i < end_position; ++i) { - if (query.Evaluate(*events.at(i))) - ++count; - } - return count; -} - -} // namespace trace_analyzer
diff --git a/base/test/trace_event_analyzer.h b/base/test/trace_event_analyzer.h deleted file mode 100644 index dcdd2e4..0000000 --- a/base/test/trace_event_analyzer.h +++ /dev/null
@@ -1,842 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Use trace_analyzer::Query and trace_analyzer::TraceAnalyzer to search for -// specific trace events that were generated by the trace_event.h API. -// -// Basic procedure: -// - Get trace events JSON string from base::trace_event::TraceLog. -// - Create TraceAnalyzer with JSON string. -// - Call TraceAnalyzer::AssociateBeginEndEvents (optional). -// - Call TraceAnalyzer::AssociateEvents (zero or more times). -// - Call TraceAnalyzer::FindEvents with queries to find specific events. -// -// A Query is a boolean expression tree that evaluates to true or false for a -// given trace event. Queries can be combined into a tree using boolean, -// arithmetic and comparison operators that refer to data of an individual trace -// event. -// -// The events are returned as trace_analyzer::TraceEvent objects. -// TraceEvent contains a single trace event's data, as well as a pointer to -// a related trace event. The related trace event is typically the matching end -// of a begin event or the matching begin of an end event. -// -// The following examples use this basic setup code to construct TraceAnalyzer -// with the json trace string retrieved from TraceLog and construct an event -// vector for retrieving events: -// -// TraceAnalyzer analyzer(json_events); -// TraceEventVector events; -// -// EXAMPLE 1: Find events named "my_event". -// -// analyzer.FindEvents(Query(EVENT_NAME) == "my_event", &events); -// -// EXAMPLE 2: Find begin events named "my_event" with duration > 1 second. -// -// Query q = (Query(EVENT_NAME) == Query::String("my_event") && -// Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_BEGIN) && -// Query(EVENT_DURATION) > Query::Double(1000000.0)); -// analyzer.FindEvents(q, &events); -// -// EXAMPLE 3: Associating event pairs across threads. -// -// If the test needs to analyze something that starts and ends on different -// threads, the test needs to use INSTANT events. The typical procedure is to -// specify the same unique ID as a TRACE_EVENT argument on both the start and -// finish INSTANT events. Then use the following procedure to associate those -// events. -// -// Step 1: instrument code with custom begin/end trace events. -// [Thread 1 tracing code] -// TRACE_EVENT_INSTANT1("test_latency", "timing1_begin", "id", 3); -// [Thread 2 tracing code] -// TRACE_EVENT_INSTANT1("test_latency", "timing1_end", "id", 3); -// -// Step 2: associate these custom begin/end pairs. -// Query begin(Query(EVENT_NAME) == Query::String("timing1_begin")); -// Query end(Query(EVENT_NAME) == Query::String("timing1_end")); -// Query match(Query(EVENT_ARG, "id") == Query(OTHER_ARG, "id")); -// analyzer.AssociateEvents(begin, end, match); -// -// Step 3: search for "timing1_begin" events with existing other event. -// Query q = (Query(EVENT_NAME) == Query::String("timing1_begin") && -// Query(EVENT_HAS_OTHER)); -// analyzer.FindEvents(q, &events); -// -// Step 4: analyze events, such as checking durations. -// for (size_t i = 0; i < events.size(); ++i) { -// double duration; -// EXPECT_TRUE(events[i].GetAbsTimeToOtherEvent(&duration)); -// EXPECT_LT(duration, 1000000.0/60.0); // expect less than 1/60 second. -// } -// -// There are two helper functions, Start(category_filter_string) and Stop(), for -// facilitating the collection of process-local traces and building a -// TraceAnalyzer from them. A typical test, that uses the helper functions, -// looks like the following: -// -// TEST_F(...) { -// Start("*"); -// [Invoke the functions you want to test their traces] -// auto analyzer = Stop(); -// -// [Use the analyzer to verify produced traces, as explained above] -// } -// -// Note: The Stop() function needs a SingleThreadTaskRunner. - -#ifndef BASE_TEST_TRACE_EVENT_ANALYZER_H_ -#define BASE_TEST_TRACE_EVENT_ANALYZER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/trace_event/trace_event.h" - -namespace base { -class Value; -} - -namespace trace_analyzer { -class QueryNode; - -// trace_analyzer::TraceEvent is a more convenient form of the -// base::trace_event::TraceEvent class to make tracing-based tests easier to -// write. -struct TraceEvent { - // ProcessThreadID contains a Process ID and Thread ID. - struct ProcessThreadID { - ProcessThreadID() : process_id(0), thread_id(0) {} - ProcessThreadID(int process_id, int thread_id) - : process_id(process_id), thread_id(thread_id) {} - bool operator< (const ProcessThreadID& rhs) const { - if (process_id != rhs.process_id) - return process_id < rhs.process_id; - return thread_id < rhs.thread_id; - } - int process_id; - int thread_id; - }; - - TraceEvent(); - TraceEvent(TraceEvent&& other); - ~TraceEvent(); - - bool SetFromJSON(const base::Value* event_value) WARN_UNUSED_RESULT; - - bool operator< (const TraceEvent& rhs) const { - return timestamp < rhs.timestamp; - } - - TraceEvent& operator=(TraceEvent&& rhs); - - bool has_other_event() const { return other_event; } - - // Returns absolute duration in microseconds between this event and other - // event. Must have already verified that other_event exists by - // Query(EVENT_HAS_OTHER) or by calling has_other_event(). - double GetAbsTimeToOtherEvent() const; - - // Return the argument value if it exists and it is a string. - bool GetArgAsString(const std::string& name, std::string* arg) const; - // Return the argument value if it exists and it is a number. - bool GetArgAsNumber(const std::string& name, double* arg) const; - // Return the argument value if it exists. - bool GetArgAsValue(const std::string& name, - std::unique_ptr<base::Value>* arg) const; - - // Check if argument exists and is string. - bool HasStringArg(const std::string& name) const; - // Check if argument exists and is number (double, int or bool). - bool HasNumberArg(const std::string& name) const; - // Check if argument exists. - bool HasArg(const std::string& name) const; - - // Get known existing arguments as specific types. - // Useful when you have already queried the argument with - // Query(HAS_NUMBER_ARG) or Query(HAS_STRING_ARG). - std::string GetKnownArgAsString(const std::string& name) const; - double GetKnownArgAsDouble(const std::string& name) const; - int GetKnownArgAsInt(const std::string& name) const; - bool GetKnownArgAsBool(const std::string& name) const; - std::unique_ptr<base::Value> GetKnownArgAsValue( - const std::string& name) const; - - // Process ID and Thread ID. - ProcessThreadID thread; - - // Time since epoch in microseconds. - // Stored as double to match its JSON representation. - double timestamp; - double duration; - char phase; - std::string category; - std::string name; - std::string id; - double thread_duration = 0.0; - double thread_timestamp = 0.0; - std::string scope; - std::string bind_id; - bool flow_out = false; - bool flow_in = false; - std::string global_id2; - std::string local_id2; - - // All numbers and bool values from TraceEvent args are cast to double. - // bool becomes 1.0 (true) or 0.0 (false). - std::map<std::string, double> arg_numbers; - std::map<std::string, std::string> arg_strings; - std::map<std::string, std::unique_ptr<base::Value>> arg_values; - - // The other event associated with this event (or NULL). - const TraceEvent* other_event; - - // A back-link for |other_event|. That is, if other_event is not null, then - // |event->other_event->prev_event == event| is always true. - const TraceEvent* prev_event; -}; - -typedef std::vector<const TraceEvent*> TraceEventVector; - -class Query { - public: - Query(const Query& query); - - ~Query(); - - //////////////////////////////////////////////////////////////// - // Query literal values - - // Compare with the given string. - static Query String(const std::string& str); - - // Compare with the given number. - static Query Double(double num); - static Query Int(int32_t num); - static Query Uint(uint32_t num); - - // Compare with the given bool. - static Query Bool(bool boolean); - - // Compare with the given phase. - static Query Phase(char phase); - - // Compare with the given string pattern. Only works with == and != operators. - // Example: Query(EVENT_NAME) == Query::Pattern("MyEvent*") - static Query Pattern(const std::string& pattern); - - //////////////////////////////////////////////////////////////// - // Query event members - - static Query EventPid() { return Query(EVENT_PID); } - - static Query EventTid() { return Query(EVENT_TID); } - - // Return the timestamp of the event in microseconds since epoch. - static Query EventTime() { return Query(EVENT_TIME); } - - // Return the absolute time between event and other event in microseconds. - // Only works if Query::EventHasOther() == true. - static Query EventDuration() { return Query(EVENT_DURATION); } - - // Return the duration of a COMPLETE event. - static Query EventCompleteDuration() { - return Query(EVENT_COMPLETE_DURATION); - } - - static Query EventPhase() { return Query(EVENT_PHASE); } - - static Query EventCategory() { return Query(EVENT_CATEGORY); } - - static Query EventName() { return Query(EVENT_NAME); } - - static Query EventId() { return Query(EVENT_ID); } - - static Query EventPidIs(int process_id) { - return Query(EVENT_PID) == Query::Int(process_id); - } - - static Query EventTidIs(int thread_id) { - return Query(EVENT_TID) == Query::Int(thread_id); - } - - static Query EventThreadIs(const TraceEvent::ProcessThreadID& thread) { - return EventPidIs(thread.process_id) && EventTidIs(thread.thread_id); - } - - static Query EventTimeIs(double timestamp) { - return Query(EVENT_TIME) == Query::Double(timestamp); - } - - static Query EventDurationIs(double duration) { - return Query(EVENT_DURATION) == Query::Double(duration); - } - - static Query EventPhaseIs(char phase) { - return Query(EVENT_PHASE) == Query::Phase(phase); - } - - static Query EventCategoryIs(const std::string& category) { - return Query(EVENT_CATEGORY) == Query::String(category); - } - - static Query EventNameIs(const std::string& name) { - return Query(EVENT_NAME) == Query::String(name); - } - - static Query EventIdIs(const std::string& id) { - return Query(EVENT_ID) == Query::String(id); - } - - // Evaluates to true if arg exists and is a string. - static Query EventHasStringArg(const std::string& arg_name) { - return Query(EVENT_HAS_STRING_ARG, arg_name); - } - - // Evaluates to true if arg exists and is a number. - // Number arguments include types double, int and bool. - static Query EventHasNumberArg(const std::string& arg_name) { - return Query(EVENT_HAS_NUMBER_ARG, arg_name); - } - - // Evaluates to arg value (string or number). - static Query EventArg(const std::string& arg_name) { - return Query(EVENT_ARG, arg_name); - } - - // Return true if associated event exists. - static Query EventHasOther() { return Query(EVENT_HAS_OTHER); } - - // Access the associated other_event's members: - - static Query OtherPid() { return Query(OTHER_PID); } - - static Query OtherTid() { return Query(OTHER_TID); } - - static Query OtherTime() { return Query(OTHER_TIME); } - - static Query OtherPhase() { return Query(OTHER_PHASE); } - - static Query OtherCategory() { return Query(OTHER_CATEGORY); } - - static Query OtherName() { return Query(OTHER_NAME); } - - static Query OtherId() { return Query(OTHER_ID); } - - static Query OtherPidIs(int process_id) { - return Query(OTHER_PID) == Query::Int(process_id); - } - - static Query OtherTidIs(int thread_id) { - return Query(OTHER_TID) == Query::Int(thread_id); - } - - static Query OtherThreadIs(const TraceEvent::ProcessThreadID& thread) { - return OtherPidIs(thread.process_id) && OtherTidIs(thread.thread_id); - } - - static Query OtherTimeIs(double timestamp) { - return Query(OTHER_TIME) == Query::Double(timestamp); - } - - static Query OtherPhaseIs(char phase) { - return Query(OTHER_PHASE) == Query::Phase(phase); - } - - static Query OtherCategoryIs(const std::string& category) { - return Query(OTHER_CATEGORY) == Query::String(category); - } - - static Query OtherNameIs(const std::string& name) { - return Query(OTHER_NAME) == Query::String(name); - } - - static Query OtherIdIs(const std::string& id) { - return Query(OTHER_ID) == Query::String(id); - } - - // Evaluates to true if arg exists and is a string. - static Query OtherHasStringArg(const std::string& arg_name) { - return Query(OTHER_HAS_STRING_ARG, arg_name); - } - - // Evaluates to true if arg exists and is a number. - // Number arguments include types double, int and bool. - static Query OtherHasNumberArg(const std::string& arg_name) { - return Query(OTHER_HAS_NUMBER_ARG, arg_name); - } - - // Evaluates to arg value (string or number). - static Query OtherArg(const std::string& arg_name) { - return Query(OTHER_ARG, arg_name); - } - - // Access the associated prev_event's members: - - static Query PrevPid() { return Query(PREV_PID); } - - static Query PrevTid() { return Query(PREV_TID); } - - static Query PrevTime() { return Query(PREV_TIME); } - - static Query PrevPhase() { return Query(PREV_PHASE); } - - static Query PrevCategory() { return Query(PREV_CATEGORY); } - - static Query PrevName() { return Query(PREV_NAME); } - - static Query PrevId() { return Query(PREV_ID); } - - static Query PrevPidIs(int process_id) { - return Query(PREV_PID) == Query::Int(process_id); - } - - static Query PrevTidIs(int thread_id) { - return Query(PREV_TID) == Query::Int(thread_id); - } - - static Query PrevThreadIs(const TraceEvent::ProcessThreadID& thread) { - return PrevPidIs(thread.process_id) && PrevTidIs(thread.thread_id); - } - - static Query PrevTimeIs(double timestamp) { - return Query(PREV_TIME) == Query::Double(timestamp); - } - - static Query PrevPhaseIs(char phase) { - return Query(PREV_PHASE) == Query::Phase(phase); - } - - static Query PrevCategoryIs(const std::string& category) { - return Query(PREV_CATEGORY) == Query::String(category); - } - - static Query PrevNameIs(const std::string& name) { - return Query(PREV_NAME) == Query::String(name); - } - - static Query PrevIdIs(const std::string& id) { - return Query(PREV_ID) == Query::String(id); - } - - // Evaluates to true if arg exists and is a string. - static Query PrevHasStringArg(const std::string& arg_name) { - return Query(PREV_HAS_STRING_ARG, arg_name); - } - - // Evaluates to true if arg exists and is a number. - // Number arguments include types double, int and bool. - static Query PrevHasNumberArg(const std::string& arg_name) { - return Query(PREV_HAS_NUMBER_ARG, arg_name); - } - - // Evaluates to arg value (string or number). - static Query PrevArg(const std::string& arg_name) { - return Query(PREV_ARG, arg_name); - } - - //////////////////////////////////////////////////////////////// - // Common queries: - - // Find BEGIN events that have a corresponding END event. - static Query MatchBeginWithEnd() { - return (Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_BEGIN)) && - Query(EVENT_HAS_OTHER); - } - - // Find COMPLETE events. - static Query MatchComplete() { - return (Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_COMPLETE)); - } - - // Find ASYNC_BEGIN events that have a corresponding ASYNC_END event. - static Query MatchAsyncBeginWithNext() { - return (Query(EVENT_PHASE) == - Query::Phase(TRACE_EVENT_PHASE_ASYNC_BEGIN)) && - Query(EVENT_HAS_OTHER); - } - - // Find BEGIN events of given |name| which also have associated END events. - static Query MatchBeginName(const std::string& name) { - return (Query(EVENT_NAME) == Query(name)) && MatchBeginWithEnd(); - } - - // Find COMPLETE events of given |name|. - static Query MatchCompleteName(const std::string& name) { - return (Query(EVENT_NAME) == Query(name)) && MatchComplete(); - } - - // Match given Process ID and Thread ID. - static Query MatchThread(const TraceEvent::ProcessThreadID& thread) { - return (Query(EVENT_PID) == Query::Int(thread.process_id)) && - (Query(EVENT_TID) == Query::Int(thread.thread_id)); - } - - // Match event pair that spans multiple threads. - static Query MatchCrossThread() { - return (Query(EVENT_PID) != Query(OTHER_PID)) || - (Query(EVENT_TID) != Query(OTHER_TID)); - } - - //////////////////////////////////////////////////////////////// - // Operators: - - // Boolean operators: - Query operator==(const Query& rhs) const; - Query operator!=(const Query& rhs) const; - Query operator< (const Query& rhs) const; - Query operator<=(const Query& rhs) const; - Query operator> (const Query& rhs) const; - Query operator>=(const Query& rhs) const; - Query operator&&(const Query& rhs) const; - Query operator||(const Query& rhs) const; - Query operator!() const; - - // Arithmetic operators: - // Following operators are applied to double arguments: - Query operator+(const Query& rhs) const; - Query operator-(const Query& rhs) const; - Query operator*(const Query& rhs) const; - Query operator/(const Query& rhs) const; - Query operator-() const; - // Mod operates on int64_t args (doubles are casted to int64_t beforehand): - Query operator%(const Query& rhs) const; - - // Return true if the given event matches this query tree. - // This is a recursive method that walks the query tree. - bool Evaluate(const TraceEvent& event) const; - - enum TraceEventMember { - EVENT_INVALID, - EVENT_PID, - EVENT_TID, - EVENT_TIME, - EVENT_DURATION, - EVENT_COMPLETE_DURATION, - EVENT_PHASE, - EVENT_CATEGORY, - EVENT_NAME, - EVENT_ID, - EVENT_HAS_STRING_ARG, - EVENT_HAS_NUMBER_ARG, - EVENT_ARG, - EVENT_HAS_OTHER, - EVENT_HAS_PREV, - - OTHER_PID, - OTHER_TID, - OTHER_TIME, - OTHER_PHASE, - OTHER_CATEGORY, - OTHER_NAME, - OTHER_ID, - OTHER_HAS_STRING_ARG, - OTHER_HAS_NUMBER_ARG, - OTHER_ARG, - - PREV_PID, - PREV_TID, - PREV_TIME, - PREV_PHASE, - PREV_CATEGORY, - PREV_NAME, - PREV_ID, - PREV_HAS_STRING_ARG, - PREV_HAS_NUMBER_ARG, - PREV_ARG, - - OTHER_FIRST_MEMBER = OTHER_PID, - OTHER_LAST_MEMBER = OTHER_ARG, - - PREV_FIRST_MEMBER = PREV_PID, - PREV_LAST_MEMBER = PREV_ARG, - }; - - enum Operator { - OP_INVALID, - // Boolean operators: - OP_EQ, - OP_NE, - OP_LT, - OP_LE, - OP_GT, - OP_GE, - OP_AND, - OP_OR, - OP_NOT, - // Arithmetic operators: - OP_ADD, - OP_SUB, - OP_MUL, - OP_DIV, - OP_MOD, - OP_NEGATE - }; - - enum QueryType { - QUERY_BOOLEAN_OPERATOR, - QUERY_ARITHMETIC_OPERATOR, - QUERY_EVENT_MEMBER, - QUERY_NUMBER, - QUERY_STRING - }; - - // Compare with the given member. - explicit Query(TraceEventMember member); - - // Compare with the given member argument value. - Query(TraceEventMember member, const std::string& arg_name); - - // Compare with the given string. - explicit Query(const std::string& str); - - // Compare with the given number. - explicit Query(double num); - - // Construct a boolean Query that returns (left <binary_op> right). - Query(const Query& left, const Query& right, Operator binary_op); - - // Construct a boolean Query that returns (<binary_op> left). - Query(const Query& left, Operator unary_op); - - // Try to compare left_ against right_ based on operator_. - // If either left or right does not convert to double, false is returned. - // Otherwise, true is returned and |result| is set to the comparison result. - bool CompareAsDouble(const TraceEvent& event, bool* result) const; - - // Try to compare left_ against right_ based on operator_. - // If either left or right does not convert to string, false is returned. - // Otherwise, true is returned and |result| is set to the comparison result. - bool CompareAsString(const TraceEvent& event, bool* result) const; - - // Attempt to convert this Query to a double. On success, true is returned - // and the double value is stored in |num|. - bool GetAsDouble(const TraceEvent& event, double* num) const; - - // Attempt to convert this Query to a string. On success, true is returned - // and the string value is stored in |str|. - bool GetAsString(const TraceEvent& event, std::string* str) const; - - // Evaluate this Query as an arithmetic operator on left_ and right_. - bool EvaluateArithmeticOperator(const TraceEvent& event, - double* num) const; - - // For QUERY_EVENT_MEMBER Query: attempt to get the double value of the Query. - bool GetMemberValueAsDouble(const TraceEvent& event, double* num) const; - - // For QUERY_EVENT_MEMBER Query: attempt to get the string value of the Query. - bool GetMemberValueAsString(const TraceEvent& event, std::string* num) const; - - // Does this Query represent a value? - bool is_value() const { return type_ != QUERY_BOOLEAN_OPERATOR; } - - bool is_unary_operator() const { - return operator_ == OP_NOT || operator_ == OP_NEGATE; - } - - bool is_comparison_operator() const { - return operator_ != OP_INVALID && operator_ < OP_AND; - } - - static const TraceEvent* SelectTargetEvent(const TraceEvent* ev, - TraceEventMember member); - - const Query& left() const; - const Query& right() const; - - private: - QueryType type_; - Operator operator_; - scoped_refptr<QueryNode> left_; - scoped_refptr<QueryNode> right_; - TraceEventMember member_; - double number_; - std::string string_; - bool is_pattern_; -}; - -// Implementation detail: -// QueryNode allows Query to store a ref-counted query tree. -class QueryNode : public base::RefCounted<QueryNode> { - public: - explicit QueryNode(const Query& query); - const Query& query() const { return query_; } - - private: - friend class base::RefCounted<QueryNode>; - ~QueryNode(); - - Query query_; -}; - -// TraceAnalyzer helps tests search for trace events. -class TraceAnalyzer { - public: - ~TraceAnalyzer(); - - // Use trace events from JSON string generated by tracing API. - // Returns non-NULL if the JSON is successfully parsed. - static TraceAnalyzer* Create(const std::string& json_events) - WARN_UNUSED_RESULT; - - void SetIgnoreMetadataEvents(bool ignore) { - ignore_metadata_events_ = ignore; - } - - // Associate BEGIN and END events with each other. This allows Query(OTHER_*) - // to access the associated event and enables Query(EVENT_DURATION). - // An end event will match the most recent begin event with the same name, - // category, process ID and thread ID. This matches what is shown in - // about:tracing. After association, the BEGIN event will point to the - // matching END event, but the END event will not point to the BEGIN event. - void AssociateBeginEndEvents(); - - // Associate ASYNC_BEGIN, ASYNC_STEP and ASYNC_END events with each other. - // An ASYNC_END event will match the most recent ASYNC_BEGIN or ASYNC_STEP - // event with the same name, category, and ID. This creates a singly linked - // list of ASYNC_BEGIN->ASYNC_STEP...->ASYNC_END. - // |match_pid| - If true, will only match async events which are running - // under the same process ID, otherwise will allow linking - // async events from different processes. - void AssociateAsyncBeginEndEvents(bool match_pid = true); - - // AssociateEvents can be used to customize event associations by setting the - // other_event member of TraceEvent. This should be used to associate two - // INSTANT events. - // - // The assumptions are: - // - |first| events occur before |second| events. - // - the closest matching |second| event is the correct match. - // - // |first| - Eligible |first| events match this query. - // |second| - Eligible |second| events match this query. - // |match| - This query is run on the |first| event. The OTHER_* EventMember - // queries will point to an eligible |second| event. The query - // should evaluate to true if the |first|/|second| pair is a match. - // - // When a match is found, the pair will be associated by having the first - // event's other_event member point to the other. AssociateEvents does not - // clear previous associations, so it is possible to associate multiple pairs - // of events by calling AssociateEvents more than once with different queries. - // - // NOTE: AssociateEvents will overwrite existing other_event associations if - // the queries pass for events that already had a previous association. - // - // After calling any Find* method, it is not allowed to call AssociateEvents - // again. - void AssociateEvents(const Query& first, - const Query& second, - const Query& match); - - // For each event, copy its arguments to the other_event argument map. If - // argument name already exists, it will not be overwritten. - void MergeAssociatedEventArgs(); - - // Find all events that match query and replace output vector. - size_t FindEvents(const Query& query, TraceEventVector* output); - - // Find first event that matches query or NULL if not found. - const TraceEvent* FindFirstOf(const Query& query); - - // Find last event that matches query or NULL if not found. - const TraceEvent* FindLastOf(const Query& query); - - const std::string& GetThreadName(const TraceEvent::ProcessThreadID& thread); - - private: - TraceAnalyzer(); - - bool SetEvents(const std::string& json_events) WARN_UNUSED_RESULT; - - // Read metadata (thread names, etc) from events. - void ParseMetadata(); - - std::map<TraceEvent::ProcessThreadID, std::string> thread_names_; - std::vector<TraceEvent> raw_events_; - bool ignore_metadata_events_; - bool allow_association_changes_; - - DISALLOW_COPY_AND_ASSIGN(TraceAnalyzer); -}; - -// Utility functions for collecting process-local traces and creating a -// |TraceAnalyzer| from the result. Please see comments in trace_config.h to -// understand how the |category_filter_string| works. Use "*" to enable all -// default categories. -void Start(const std::string& category_filter_string); -std::unique_ptr<TraceAnalyzer> Stop(); - -// Utility functions for TraceEventVector. - -struct RateStats { - double min_us; - double max_us; - double mean_us; - double standard_deviation_us; -}; - -struct RateStatsOptions { - RateStatsOptions() : trim_min(0u), trim_max(0u) {} - // After the times between events are sorted, the number of specified elements - // will be trimmed before calculating the RateStats. This is useful in cases - // where extreme outliers are tolerable and should not skew the overall - // average. - size_t trim_min; // Trim this many minimum times. - size_t trim_max; // Trim this many maximum times. -}; - -// Calculate min/max/mean and standard deviation from the times between -// adjacent events. -bool GetRateStats(const TraceEventVector& events, - RateStats* stats, - const RateStatsOptions* options); - -// Starting from |position|, find the first event that matches |query|. -// Returns true if found, false otherwise. -bool FindFirstOf(const TraceEventVector& events, - const Query& query, - size_t position, - size_t* return_index); - -// Starting from |position|, find the last event that matches |query|. -// Returns true if found, false otherwise. -bool FindLastOf(const TraceEventVector& events, - const Query& query, - size_t position, - size_t* return_index); - -// Find the closest events to |position| in time that match |query|. -// return_second_closest may be NULL. Closeness is determined by comparing -// with the event timestamp. -// Returns true if found, false otherwise. If both return parameters are -// requested, both must be found for a successful result. -bool FindClosest(const TraceEventVector& events, - const Query& query, - size_t position, - size_t* return_closest, - size_t* return_second_closest); - -// Count matches, inclusive of |begin_position|, exclusive of |end_position|. -size_t CountMatches(const TraceEventVector& events, - const Query& query, - size_t begin_position, - size_t end_position); - -// Count all matches. -static inline size_t CountMatches(const TraceEventVector& events, - const Query& query) { - return CountMatches(events, query, 0u, events.size()); -} - -} // namespace trace_analyzer - -#endif // BASE_TEST_TRACE_EVENT_ANALYZER_H_
diff --git a/base/threading/thread_id_name_manager.cc b/base/threading/thread_id_name_manager.cc index ca1979d..101b57d 100644 --- a/base/threading/thread_id_name_manager.cc +++ b/base/threading/thread_id_name_manager.cc
@@ -12,7 +12,6 @@ #include "base/no_destructor.h" #include "base/strings/string_util.h" #include "base/threading/thread_local.h" -#include "base/trace_event/heap_profiler_allocation_context_tracker.h" namespace base { namespace { @@ -88,14 +87,6 @@ } thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str; } - - // Add the leaked thread name to heap profiler context tracker. The name added - // is valid for the lifetime of the process. AllocationContextTracker cannot - // call GetName(which holds a lock) during the first allocation because it can - // cause a deadlock when the first allocation happens in the - // ThreadIdNameManager itself when holding the lock. - trace_event::AllocationContextTracker::SetCurrentThreadName( - leaked_str->c_str()); } const char* ThreadIdNameManager::GetName(PlatformThreadId id) {
diff --git a/base/trace_event/OWNERS b/base/trace_event/OWNERS deleted file mode 100644 index 24a0bd2..0000000 --- a/base/trace_event/OWNERS +++ /dev/null
@@ -1,15 +0,0 @@ -chiniforooshan@chromium.org -oysteine@chromium.org -primiano@chromium.org -per-file trace_event_android.cc=wangxianzhu@chromium.org - -# For memory-infra related changes -ssid@chromium.org - -# Emeritus: -dsinclair@chromium.org -nduca@chromium.org -simonhatch@chromium.org - -# TEAM: tracing@chromium.org -# COMPONENT: Speed>Tracing
diff --git a/base/trace_event/auto_open_close_event.cc b/base/trace_event/auto_open_close_event.cc deleted file mode 100644 index 1879700..0000000 --- a/base/trace_event/auto_open_close_event.cc +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/auto_open_close_event.h" - -#include "base/macros.h" -#include "base/time/time.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace trace_event { - -AutoOpenCloseEvent::AutoOpenCloseEvent(AutoOpenCloseEvent::Type type, - const char* category, const char* event_name): - category_(category), - event_name_(event_name), - weak_factory_(this) { - base::trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver( - weak_factory_.GetWeakPtr()); -} - -AutoOpenCloseEvent::~AutoOpenCloseEvent() { - DCHECK(thread_checker_.CalledOnValidThread()); - base::trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver( - this); -} - -void AutoOpenCloseEvent::Begin() { - DCHECK(thread_checker_.CalledOnValidThread()); - start_time_ = TRACE_TIME_TICKS_NOW(); - TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0( - category_, event_name_, static_cast<void*>(this), start_time_); -} - -void AutoOpenCloseEvent::End() { - DCHECK(thread_checker_.CalledOnValidThread()); - TRACE_EVENT_ASYNC_END0(category_, event_name_, static_cast<void*>(this)); - start_time_ = base::TimeTicks(); -} - -void AutoOpenCloseEvent::OnTraceLogEnabled() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (start_time_.ToInternalValue() != 0) - TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0( - category_, event_name_, static_cast<void*>(this), start_time_); -} - -void AutoOpenCloseEvent::OnTraceLogDisabled() {} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/auto_open_close_event.h b/base/trace_event/auto_open_close_event.h deleted file mode 100644 index 795a494..0000000 --- a/base/trace_event/auto_open_close_event.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_AUTO_OPEN_CLOSE_EVENT_H_ -#define BASE_AUTO_OPEN_CLOSE_EVENT_H_ - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "base/time/time.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace trace_event { - -// Class for tracing events that support "auto-opening" and "auto-closing". -// "auto-opening" = if the trace event is started (call Begin() before -// tracing is started,the trace event will be opened, with the start time -// being the time that the trace event was actually started. -// "auto-closing" = if the trace event is started but not ended by the time -// tracing ends, then the trace event will be automatically closed at the -// end of tracing. -class BASE_EXPORT AutoOpenCloseEvent - : public TraceLog::AsyncEnabledStateObserver { - public: - enum Type { - ASYNC - }; - - // As in the rest of the tracing macros, the const char* arguments here - // must be pointers to indefinitely lived strings (e.g. hard-coded string - // literals are okay, but not strings created by c_str()) - AutoOpenCloseEvent(Type type, const char* category, const char* event_name); - ~AutoOpenCloseEvent() override; - - void Begin(); - void End(); - - // AsyncEnabledStateObserver implementation - void OnTraceLogEnabled() override; - void OnTraceLogDisabled() override; - - private: - const char* const category_; - const char* const event_name_; - base::TimeTicks start_time_; - base::ThreadChecker thread_checker_; - WeakPtrFactory<AutoOpenCloseEvent> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(AutoOpenCloseEvent); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_AUTO_OPEN_CLOSE_EVENT_H_ \ No newline at end of file
diff --git a/base/trace_event/blame_context.cc b/base/trace_event/blame_context.cc deleted file mode 100644 index ae0b718..0000000 --- a/base/trace_event/blame_context.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/blame_context.h" - -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" - -namespace base { -namespace trace_event { - -BlameContext::BlameContext(const char* category, - const char* name, - const char* type, - const char* scope, - int64_t id, - const BlameContext* parent_context) - : category_(category), - name_(name), - type_(type), - scope_(scope), - id_(id), - parent_scope_(parent_context ? parent_context->scope() : nullptr), - parent_id_(parent_context ? parent_context->id() : 0), - category_group_enabled_(nullptr), - weak_factory_(this) { - DCHECK(!parent_context || !std::strcmp(name_, parent_context->name())) - << "Parent blame context must have the same name"; -} - -BlameContext::~BlameContext() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(WasInitialized()); - TRACE_EVENT_API_ADD_TRACE_EVENT( - TRACE_EVENT_PHASE_DELETE_OBJECT, category_group_enabled_, type_, scope_, - id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); - trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(this); -} - -void BlameContext::Enter() { - DCHECK(WasInitialized()); - TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_ENTER_CONTEXT, - category_group_enabled_, name_, scope_, id_, - 0 /* num_args */, nullptr, nullptr, nullptr, - nullptr, TRACE_EVENT_FLAG_HAS_ID); -} - -void BlameContext::Leave() { - DCHECK(WasInitialized()); - TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_LEAVE_CONTEXT, - category_group_enabled_, name_, scope_, id_, - 0 /* num_args */, nullptr, nullptr, nullptr, - nullptr, TRACE_EVENT_FLAG_HAS_ID); -} - -void BlameContext::TakeSnapshot() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(WasInitialized()); - if (!*category_group_enabled_) - return; - std::unique_ptr<trace_event::TracedValue> snapshot( - new trace_event::TracedValue); - AsValueInto(snapshot.get()); - static const char* const kArgName = "snapshot"; - const int kNumArgs = 1; - unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE}; - std::unique_ptr<trace_event::ConvertableToTraceFormat> arg_values[1] = { - std::move(snapshot)}; - TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, - category_group_enabled_, type_, scope_, id_, - kNumArgs, &kArgName, arg_types, nullptr, - arg_values, TRACE_EVENT_FLAG_HAS_ID); -} - -void BlameContext::OnTraceLogEnabled() { - DCHECK(WasInitialized()); - TakeSnapshot(); -} - -void BlameContext::OnTraceLogDisabled() {} - -void BlameContext::AsValueInto(trace_event::TracedValue* state) { - DCHECK(WasInitialized()); - if (!parent_id_) - return; - state->BeginDictionary("parent"); - state->SetString("id_ref", StringPrintf("0x%" PRIx64, parent_id_)); - state->SetString("scope", parent_scope_); - state->EndDictionary(); -} - -void BlameContext::Initialize() { - DCHECK(thread_checker_.CalledOnValidThread()); - category_group_enabled_ = - TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_); - TRACE_EVENT_API_ADD_TRACE_EVENT( - TRACE_EVENT_PHASE_CREATE_OBJECT, category_group_enabled_, type_, scope_, - id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); - trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver( - weak_factory_.GetWeakPtr()); - TakeSnapshot(); -} - -bool BlameContext::WasInitialized() const { - return category_group_enabled_ != nullptr; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/blame_context.h b/base/trace_event/blame_context.h deleted file mode 100644 index a973a28..0000000 --- a/base/trace_event/blame_context.h +++ /dev/null
@@ -1,138 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_BLAME_CONTEXT_H_ -#define BASE_TRACE_EVENT_BLAME_CONTEXT_H_ - -#include <inttypes.h> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/threading/thread_checker.h" -#include "base/trace_event/trace_log.h" - -namespace base { -namespace trace_event { -class TracedValue; -} - -namespace trace_event { - -// A blame context represents a logical unit to which we want to attribute -// different costs (e.g., CPU, network, or memory usage). An example of a blame -// context is an <iframe> element on a web page. Different subsystems can -// "enter" and "leave" blame contexts to indicate that they are doing work which -// should be accounted against this blame context. -// -// A blame context can optionally have a parent context, forming a blame context -// tree. When work is attributed to a particular blame context, it is considered -// to count against all of that context's children too. This is useful when work -// cannot be exactly attributed into a more specific context. For example, -// Javascript garbage collection generally needs to inspect all objects on a -// page instead looking at each <iframe> individually. In this case the work -// should be attributed to a blame context which is the parent of all <iframe> -// blame contexts. -class BASE_EXPORT BlameContext - : public trace_event::TraceLog::AsyncEnabledStateObserver { - public: - // Construct a blame context belonging to the blame context tree |name|, using - // the tracing category |category|, identified by |id| from the |scope| - // namespace. |type| identifies the type of this object snapshot in the blame - // context tree. |parent_context| is the parent of this blame context or - // null. Note that all strings must have application lifetime. - // - // For example, a blame context which represents a specific <iframe> in a - // browser frame tree could be specified with: - // - // category="blink", - // name="FrameTree", - // type="IFrame", - // scope="IFrameIdentifier", - // id=1234. - // - // Each <iframe> blame context could have another <iframe> context as a - // parent, or a top-level context which represents the entire browser: - // - // category="blink", - // name="FrameTree", - // type="Browser", - // scope="BrowserIdentifier", - // id=1. - // - // Note that the |name| property is identical, signifying that both context - // types are part of the same tree. - // - BlameContext(const char* category, - const char* name, - const char* type, - const char* scope, - int64_t id, - const BlameContext* parent_context); - ~BlameContext() override; - - // Initialize the blame context, automatically taking a snapshot if tracing is - // enabled. Must be called before any other methods on this class. - void Initialize(); - - // Indicate that the current thread is now doing work which should count - // against this blame context. This function is allowed to be called in a - // thread different from where the blame context was created; However, any - // client doing that must be fully responsible for ensuring thready safety. - void Enter(); - - // Leave and stop doing work for a previously entered blame context. If - // another blame context belonging to the same tree was entered prior to this - // one, it becomes the active blame context for this thread again. Similar - // to Enter(), this function can be called in a thread different from where - // the blame context was created, and the same requirement on thread safety - // must be satisfied. - void Leave(); - - // Record a snapshot of the blame context. This is normally only needed if a - // blame context subclass defines custom properties (see AsValueInto) and one - // or more of those properties have changed. - void TakeSnapshot(); - - const char* category() const { return category_; } - const char* name() const { return name_; } - const char* type() const { return type_; } - const char* scope() const { return scope_; } - int64_t id() const { return id_; } - - // trace_event::TraceLog::EnabledStateObserver implementation: - void OnTraceLogEnabled() override; - void OnTraceLogDisabled() override; - - protected: - // Serialize the properties of this blame context into |state|. Subclasses can - // override this method to record additional properties (e.g, the URL for an - // <iframe> blame context). Note that an overridden implementation must still - // call this base method. - virtual void AsValueInto(trace_event::TracedValue* state); - - private: - bool WasInitialized() const; - - // The following string pointers have application lifetime. - const char* category_; - const char* name_; - const char* type_; - const char* scope_; - const int64_t id_; - - const char* parent_scope_; - const int64_t parent_id_; - - const unsigned char* category_group_enabled_; - - ThreadChecker thread_checker_; - WeakPtrFactory<BlameContext> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(BlameContext); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_BLAME_CONTEXT_H_
diff --git a/base/trace_event/category_registry.cc b/base/trace_event/category_registry.cc deleted file mode 100644 index e7c1460..0000000 --- a/base/trace_event/category_registry.cc +++ /dev/null
@@ -1,156 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/category_registry.h" - -#include <string.h> - -#include <type_traits> - -#include "base/atomicops.h" -#include "base/debug/leak_annotations.h" -#include "base/logging.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" -#include "base/trace_event/trace_category.h" - -namespace base { -namespace trace_event { - -namespace { - -constexpr size_t kMaxCategories = 200; -const int kNumBuiltinCategories = 4; - -// |g_categories| might end up causing creating dynamic initializers if not POD. -static_assert(std::is_pod<TraceCategory>::value, "TraceCategory must be POD"); - -// These entries must be kept consistent with the kCategory* consts below. -TraceCategory g_categories[kMaxCategories] = { - {0, 0, "tracing categories exhausted; must increase kMaxCategories"}, - {0, 0, "tracing already shutdown"}, // See kCategoryAlreadyShutdown below. - {0, 0, "__metadata"}, // See kCategoryMetadata below. - {0, 0, "toplevel"}, // Warmup the toplevel category. -}; - -base::subtle::AtomicWord g_category_index = kNumBuiltinCategories; - -bool IsValidCategoryPtr(const TraceCategory* category) { - // If any of these are hit, something has cached a corrupt category pointer. - uintptr_t ptr = reinterpret_cast<uintptr_t>(category); - return ptr % sizeof(void*) == 0 && - ptr >= reinterpret_cast<uintptr_t>(&g_categories[0]) && - ptr <= reinterpret_cast<uintptr_t>(&g_categories[kMaxCategories - 1]); -} - -} // namespace - -// static -TraceCategory* const CategoryRegistry::kCategoryExhausted = &g_categories[0]; -TraceCategory* const CategoryRegistry::kCategoryAlreadyShutdown = - &g_categories[1]; -TraceCategory* const CategoryRegistry::kCategoryMetadata = &g_categories[2]; - -// static -void CategoryRegistry::Initialize() { - // Trace is enabled or disabled on one thread while other threads are - // accessing the enabled flag. We don't care whether edge-case events are - // traced or not, so we allow races on the enabled flag to keep the trace - // macros fast. - for (size_t i = 0; i < kMaxCategories; ++i) { - ANNOTATE_BENIGN_RACE(g_categories[i].state_ptr(), - "trace_event category enabled"); - // If this DCHECK is hit in a test it means that ResetForTesting() is not - // called and the categories state leaks between test fixtures. - DCHECK(!g_categories[i].is_enabled()); - } -} - -// static -void CategoryRegistry::ResetForTesting() { - // reset_for_testing clears up only the enabled state and filters. The - // categories themselves cannot be cleared up because the static pointers - // injected by the macros still point to them and cannot be reset. - for (size_t i = 0; i < kMaxCategories; ++i) - g_categories[i].reset_for_testing(); -} - -// static -TraceCategory* CategoryRegistry::GetCategoryByName(const char* category_name) { - DCHECK(!strchr(category_name, '"')) - << "Category names may not contain double quote"; - - // The g_categories is append only, avoid using a lock for the fast path. - size_t category_index = base::subtle::Acquire_Load(&g_category_index); - - // Search for pre-existing category group. - for (size_t i = 0; i < category_index; ++i) { - if (strcmp(g_categories[i].name(), category_name) == 0) { - return &g_categories[i]; - } - } - return nullptr; -} - -bool CategoryRegistry::GetOrCreateCategoryLocked( - const char* category_name, - CategoryInitializerFn category_initializer_fn, - TraceCategory** category) { - // This is the slow path: the lock is not held in the fastpath - // (GetCategoryByName), so more than one thread could have reached here trying - // to add the same category. - *category = GetCategoryByName(category_name); - if (*category) - return false; - - // Create a new category. - size_t category_index = base::subtle::Acquire_Load(&g_category_index); - if (category_index >= kMaxCategories) { - NOTREACHED() << "must increase kMaxCategories"; - *category = kCategoryExhausted; - return false; - } - - // TODO(primiano): this strdup should be removed. The only documented reason - // for it was TraceWatchEvent, which is gone. However, something might have - // ended up relying on this. Needs some auditing before removal. - const char* category_name_copy = strdup(category_name); - ANNOTATE_LEAKING_OBJECT_PTR(category_name_copy); - - *category = &g_categories[category_index]; - DCHECK(!(*category)->is_valid()); - DCHECK(!(*category)->is_enabled()); - (*category)->set_name(category_name_copy); - category_initializer_fn(*category); - - // Update the max index now. - base::subtle::Release_Store(&g_category_index, category_index + 1); - return true; -} - -// static -const TraceCategory* CategoryRegistry::GetCategoryByStatePtr( - const uint8_t* category_state) { - const TraceCategory* category = TraceCategory::FromStatePtr(category_state); - DCHECK(IsValidCategoryPtr(category)); - return category; -} - -// static -bool CategoryRegistry::IsBuiltinCategory(const TraceCategory* category) { - DCHECK(IsValidCategoryPtr(category)); - return category < &g_categories[kNumBuiltinCategories]; -} - -// static -CategoryRegistry::Range CategoryRegistry::GetAllCategories() { - // The |g_categories| array is append only. We have to only guarantee to - // not return an index to a category which is being initialized by - // GetOrCreateCategoryByName(). - size_t category_index = base::subtle::Acquire_Load(&g_category_index); - return CategoryRegistry::Range(&g_categories[0], - &g_categories[category_index]); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/category_registry.h b/base/trace_event/category_registry.h deleted file mode 100644 index 9c08efa..0000000 --- a/base/trace_event/category_registry.h +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_ -#define BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/base_export.h" -#include "base/logging.h" - -namespace base { -namespace trace_event { - -struct TraceCategory; -class TraceCategoryTest; -class TraceLog; - -// Allows fast and thread-safe acces to the state of all tracing categories. -// All the methods in this class can be concurrently called on multiple threads, -// unless otherwise noted (e.g., GetOrCreateCategoryLocked). -// The reason why this is a fully static class with global state is to allow to -// statically define known categories as global linker-initialized structs, -// without requiring static initializers. -class BASE_EXPORT CategoryRegistry { - public: - // Allows for-each iterations over a slice of the categories array. - class Range { - public: - Range(TraceCategory* begin, TraceCategory* end) : begin_(begin), end_(end) { - DCHECK_LE(begin, end); - } - TraceCategory* begin() const { return begin_; } - TraceCategory* end() const { return end_; } - - private: - TraceCategory* const begin_; - TraceCategory* const end_; - }; - - // Known categories. - static TraceCategory* const kCategoryExhausted; - static TraceCategory* const kCategoryMetadata; - static TraceCategory* const kCategoryAlreadyShutdown; - - // Returns a category entry from the Category.state_ptr() pointer. - // TODO(primiano): trace macros should just keep a pointer to the entire - // TraceCategory, not just the enabled state pointer. That would remove the - // need for this function and make everything cleaner at no extra cost (as - // long as the |state_| is the first field of the struct, which can be - // guaranteed via static_assert, see TraceCategory ctor). - static const TraceCategory* GetCategoryByStatePtr( - const uint8_t* category_state); - - // Returns a category from its name or nullptr if not found. - // The output |category| argument is an undefinitely lived pointer to the - // TraceCategory owned by the registry. TRACE_EVENTx macros will cache this - // pointer and use it for checks in their fast-paths. - static TraceCategory* GetCategoryByName(const char* category_name); - - static bool IsBuiltinCategory(const TraceCategory*); - - private: - friend class TraceCategoryTest; - friend class TraceLog; - using CategoryInitializerFn = void (*)(TraceCategory*); - - // Only for debugging/testing purposes, is a no-op on release builds. - static void Initialize(); - - // Resets the state of all categories, to clear up the state between tests. - static void ResetForTesting(); - - // Used to get/create a category in the slow-path. If the category exists - // already, this has the same effect of GetCategoryByName and returns false. - // If not, a new category is created and the CategoryInitializerFn is invoked - // before retuning true. The caller must guarantee serialization: either call - // this method from a single thread or hold a lock when calling this. - static bool GetOrCreateCategoryLocked(const char* category_name, - CategoryInitializerFn, - TraceCategory**); - - // Allows to iterate over the valid categories in a for-each loop. - // This includes builtin categories such as __metadata. - static Range GetAllCategories(); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
diff --git a/base/trace_event/common/trace_event_common.h b/base/trace_event/common/trace_event_common.h deleted file mode 100644 index e2a5ca0..0000000 --- a/base/trace_event/common/trace_event_common.h +++ /dev/null
@@ -1,1114 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_COMMON_TRACE_EVENT_COMMON_H_ -#define BASE_TRACE_EVENT_COMMON_TRACE_EVENT_COMMON_H_ - -// This header file defines the set of trace_event macros without specifying -// how the events actually get collected and stored. If you need to expose trace -// events to some other universe, you can copy-and-paste this file as well as -// trace_event.h, modifying the macros contained there as necessary for the -// target platform. The end result is that multiple libraries can funnel events -// through to a shared trace event collector. - -// IMPORTANT: To avoid conflicts, if you need to modify this file for a library, -// land your change in base/ first, and then copy-and-paste it. - -// Trace events are for tracking application performance and resource usage. -// Macros are provided to track: -// Begin and end of function calls -// Counters -// -// Events are issued against categories. Whereas LOG's -// categories are statically defined, TRACE categories are created -// implicitly with a string. For example: -// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent", -// TRACE_EVENT_SCOPE_THREAD) -// -// It is often the case that one trace may belong in multiple categories at the -// same time. The first argument to the trace can be a comma-separated list of -// categories, forming a category group, like: -// -// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver", TRACE_EVENT_SCOPE_THREAD) -// -// We can enable/disable tracing of OnMouseOver by enabling/disabling either -// category. -// -// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: -// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") -// doSomethingCostly() -// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") -// Note: our tools can't always determine the correct BEGIN/END pairs unless -// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you -// need them to be in separate scopes. -// -// A common use case is to trace entire function scopes. This -// issues a trace BEGIN and END automatically: -// void doSomethingCostly() { -// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); -// ... -// } -// -// Additional parameters can be associated with an event: -// void doSomethingCostly2(int howMuch) { -// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", -// "howMuch", howMuch); -// ... -// } -// -// The trace system will automatically add to this information the -// current process id, thread id, and a timestamp in microseconds. -// -// To trace an asynchronous procedure such as an IPC send/receive, use -// ASYNC_BEGIN and ASYNC_END: -// [single threaded sender code] -// static int send_count = 0; -// ++send_count; -// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); -// Send(new MyMessage(send_count)); -// [receive code] -// void OnMyMessage(send_count) { -// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); -// } -// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. -// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. -// Pointers can be used for the ID parameter, and they will be mangled -// internally so that the same pointer on two different processes will not -// match. For example: -// class MyTracedClass { -// public: -// MyTracedClass() { -// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); -// } -// ~MyTracedClass() { -// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); -// } -// } -// -// Trace event also supports counters, which is a way to track a quantity -// as it varies over time. Counters are created with the following macro: -// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); -// -// Counters are process-specific. The macro itself can be issued from any -// thread, however. -// -// Sometimes, you want to track two counters at once. You can do this with two -// counter macros: -// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); -// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); -// Or you can do it with a combined macro: -// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", -// "bytesPinned", g_myCounterValue[0], -// "bytesAllocated", g_myCounterValue[1]); -// This indicates to the tracing UI that these counters should be displayed -// in a single graph, as a summed area chart. -// -// Since counters are in a global namespace, you may want to disambiguate with a -// unique ID, by using the TRACE_COUNTER_ID* variations. -// -// By default, trace collection is compiled in, but turned off at runtime. -// Collecting trace data is the responsibility of the embedding -// application. In Chrome's case, navigating to about:tracing will turn on -// tracing and display data collected across all active processes. -// -// -// Memory scoping note: -// Tracing copies the pointers, not the string content, of the strings passed -// in for category_group, name, and arg_names. Thus, the following code will -// cause problems: -// char* str = strdup("importantName"); -// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! -// free(str); // Trace system now has dangling pointer -// -// To avoid this issue with the |name| and |arg_name| parameters, use the -// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. -// Notes: The category must always be in a long-lived char* (i.e. static const). -// The |arg_values|, when used, are always deep copied with the _COPY -// macros. -// -// When are string argument values copied: -// const char* arg_values are only referenced by default: -// TRACE_EVENT1("category", "name", -// "arg1", "literal string is only referenced"); -// Use TRACE_STR_COPY to force copying of a const char*: -// TRACE_EVENT1("category", "name", -// "arg1", TRACE_STR_COPY("string will be copied")); -// std::string arg_values are always copied: -// TRACE_EVENT1("category", "name", -// "arg1", std::string("string will be copied")); -// -// -// Convertable notes: -// Converting a large data type to a string can be costly. To help with this, -// the trace framework provides an interface ConvertableToTraceFormat. If you -// inherit from it and implement the AppendAsTraceFormat method the trace -// framework will call back to your object to convert a trace output time. This -// means, if the category for the event is disabled, the conversion will not -// happen. -// -// class MyData : public base::trace_event::ConvertableToTraceFormat { -// public: -// MyData() {} -// void AppendAsTraceFormat(std::string* out) const override { -// out->append("{\"foo\":1}"); -// } -// private: -// ~MyData() override {} -// DISALLOW_COPY_AND_ASSIGN(MyData); -// }; -// -// TRACE_EVENT1("foo", "bar", "data", -// std::unique_ptr<ConvertableToTraceFormat>(new MyData())); -// -// The trace framework will take ownership if the passed pointer and it will -// be free'd when the trace buffer is flushed. -// -// Note, we only do the conversion when the buffer is flushed, so the provided -// data object should not be modified after it's passed to the trace framework. -// -// -// Thread Safety: -// A thread safe singleton and mutex are used for thread safety. Category -// enabled flags are used to limit the performance impact when the system -// is not enabled. -// -// TRACE_EVENT macros first cache a pointer to a category. The categories are -// statically allocated and safe at all times, even after exit. Fetching a -// category is protected by the TraceLog::lock_. Multiple threads initializing -// the static variable is safe, as they will be serialized by the lock and -// multiple calls will return the same pointer to the category. -// -// Then the category_group_enabled flag is checked. This is a unsigned char, and -// not intended to be multithread safe. It optimizes access to AddTraceEvent -// which is threadsafe internally via TraceLog::lock_. The enabled flag may -// cause some threads to incorrectly call or skip calling AddTraceEvent near -// the time of the system being enabled or disabled. This is acceptable as -// we tolerate some data loss while the system is being enabled/disabled and -// because AddTraceEvent is threadsafe internally and checks the enabled state -// again under lock. -// -// Without the use of these static category pointers and enabled flags all -// trace points would carry a significant performance cost of acquiring a lock -// and resolving the category. - -// Check that nobody includes this file directly. Clients are supposed to -// include the surrounding "trace_event.h" of their project instead. -#if defined(TRACE_EVENT0) -#error "Another copy of this file has already been included." -#endif - -// This will mark the trace event as disabled by default. The user will need -// to explicitly enable the event. -#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name - -// Records a pair of begin and end events called "name" for the current -// scope, with 0, 1 or 2 associated arguments. If the category is not -// enabled, then this does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name) -#define TRACE_EVENT_WITH_FLOW0(category_group, name, bind_id, flow_flags) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, bind_id, \ - flow_flags) -#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val) -#define TRACE_EVENT_WITH_FLOW1(category_group, name, bind_id, flow_flags, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, bind_id, \ - flow_flags, arg1_name, arg1_val) -#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, \ - arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#define TRACE_EVENT_WITH_FLOW2(category_group, name, bind_id, flow_flags, \ - arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, bind_id, \ - flow_flags, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -// Records a single event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT_INSTANT0(category_group, name, scope) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ - TRACE_EVENT_FLAG_NONE | scope) -#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ - TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val) -#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ - TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#define TRACE_EVENT_COPY_INSTANT0(category_group, name, scope) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ - TRACE_EVENT_FLAG_COPY | scope) -#define TRACE_EVENT_COPY_INSTANT1(category_group, name, scope, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ - TRACE_EVENT_FLAG_COPY | scope, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_INSTANT2(category_group, name, scope, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ - TRACE_EVENT_FLAG_COPY | scope, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -#define TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(category_group, name, scope, \ - timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_INSTANT, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_NONE | scope) - -#define TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(category_group, name, scope, \ - timestamp, arg_name, arg_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_INSTANT, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_NONE | scope, arg_name, arg_val) - -// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT_BEGIN0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_BEGIN1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_BEGIN2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#define TRACE_EVENT_COPY_BEGIN0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ - TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_BEGIN1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_BEGIN2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -// Similar to TRACE_EVENT_BEGINx but with a custom |at| timestamp provided. -// - |id| is used to match the _BEGIN event with the _END event. -// Events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -#define TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category_group, name, id, \ - thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( \ - category_group, name, id, thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP1( \ - category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP2( \ - category_group, name, id, thread_id, timestamp, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \ - arg2_val) - -// Records a single END event for "name" immediately. If the category -// is not enabled, then this does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT_END0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_END1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_END2(category_group, name, arg1_name, arg1_val, arg2_name, \ - arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#define TRACE_EVENT_COPY_END0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ - TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_END1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_END2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -#define TRACE_EVENT_MARK_WITH_TIMESTAMP0(category_group, name, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_NONE) - -#define TRACE_EVENT_MARK_WITH_TIMESTAMP1(category_group, name, timestamp, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) - -#define TRACE_EVENT_MARK_WITH_TIMESTAMP2( \ - category_group, name, timestamp, arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) - -#define TRACE_EVENT_COPY_MARK(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_MARK, category_group, name, \ - TRACE_EVENT_FLAG_COPY) - -#define TRACE_EVENT_COPY_MARK_WITH_TIMESTAMP(category_group, name, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_COPY) - -// Similar to TRACE_EVENT_ENDx but with a custom |at| timestamp provided. -// - |id| is used to match the _BEGIN event with the _END event. -// Events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -#define TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(category_group, name, id, \ - thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( \ - category_group, name, id, thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP1( \ - category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP2( \ - category_group, name, id, thread_id, timestamp, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \ - arg2_val) - -// Records the value of a counter called "name" immediately. Value -// must be representable as a 32 bit integer. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_COUNTER1(category_group, name, value) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \ - TRACE_EVENT_FLAG_NONE, "value", \ - static_cast<int>(value)) -#define TRACE_COPY_COUNTER1(category_group, name, value) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \ - TRACE_EVENT_FLAG_COPY, "value", \ - static_cast<int>(value)) - -// Records the values of a multi-parted counter called "name" immediately. -// The UI will treat value1 and value2 as parts of a whole, displaying their -// values as a stacked-bar chart. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \ - value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \ - TRACE_EVENT_FLAG_NONE, value1_name, \ - static_cast<int>(value1_val), value2_name, \ - static_cast<int>(value2_val)) -#define TRACE_COPY_COUNTER2(category_group, name, value1_name, value1_val, \ - value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \ - TRACE_EVENT_FLAG_COPY, value1_name, \ - static_cast<int>(value1_val), value2_name, \ - static_cast<int>(value2_val)) - -// Similar to TRACE_COUNTERx, but with a custom |timestamp| provided. -#define TRACE_COUNTER_WITH_TIMESTAMP1(category_group, name, timestamp, value) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value)) - -#define TRACE_COUNTER_WITH_TIMESTAMP2(category_group, name, timestamp, \ - value1_name, value1_val, value2_name, \ - value2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \ - TRACE_EVENT_FLAG_NONE, value1_name, static_cast<int>(value1_val), \ - value2_name, static_cast<int>(value2_val)) - -// Records the value of a counter called "name" immediately. Value -// must be representable as a 32 bit integer. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to disambiguate counters with the same name. It must either -// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits -// will be xored with a hash of the process ID so that the same pointer on -// two different processes will not collide. -#define TRACE_COUNTER_ID1(category_group, name, id, value) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \ - name, id, TRACE_EVENT_FLAG_NONE, "value", \ - static_cast<int>(value)) -#define TRACE_COPY_COUNTER_ID1(category_group, name, id, value) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \ - name, id, TRACE_EVENT_FLAG_COPY, "value", \ - static_cast<int>(value)) - -// Records the values of a multi-parted counter called "name" immediately. -// The UI will treat value1 and value2 as parts of a whole, displaying their -// values as a stacked-bar chart. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to disambiguate counters with the same name. It must either -// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits -// will be xored with a hash of the process ID so that the same pointer on -// two different processes will not collide. -#define TRACE_COUNTER_ID2(category_group, name, id, value1_name, value1_val, \ - value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \ - name, id, TRACE_EVENT_FLAG_NONE, \ - value1_name, static_cast<int>(value1_val), \ - value2_name, static_cast<int>(value2_val)) -#define TRACE_COPY_COUNTER_ID2(category_group, name, id, value1_name, \ - value1_val, value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \ - name, id, TRACE_EVENT_FLAG_COPY, \ - value1_name, static_cast<int>(value1_val), \ - value2_name, static_cast<int>(value2_val)) - -// TRACE_EVENT_SAMPLE_* events are injected by the sampling profiler. -#define TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP0(category_group, name, \ - thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_SAMPLE, category_group, name, 0, thread_id, timestamp, \ - TRACE_EVENT_FLAG_NONE) - -#define TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP1( \ - category_group, name, thread_id, timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_SAMPLE, category_group, name, 0, thread_id, timestamp, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) - -#define TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP2(category_group, name, \ - thread_id, timestamp, \ - arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_SAMPLE, category_group, name, 0, thread_id, timestamp, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) - -#define TRACE_EVENT_SAMPLE_WITH_ID1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_SAMPLE, category_group, \ - name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \ - arg1_val) - -// ASYNC_STEP_* APIs should be only used by legacy code. New code should -// consider using NESTABLE_ASYNC_* APIs to describe substeps within an async -// event. -// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC -// events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -// -// An asynchronous operation can consist of multiple phases. The first phase is -// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the -// ASYNC_STEP_INTO or ASYNC_STEP_PAST macros. The ASYNC_STEP_INTO macro will -// annotate the block following the call. The ASYNC_STEP_PAST macro will -// annotate the block prior to the call. Note that any particular event must use -// only STEP_INTO or STEP_PAST macros; they can not mix and match. When the -// operation completes, call ASYNC_END. -// -// An ASYNC trace typically occurs on a single thread (if not, they will only be -// drawn on the thread defined in the ASYNC_BEGIN event), but all events in that -// operation must use the same |name| and |id|. Each step can have its own -// args. -#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) - -// Similar to TRACE_EVENT_ASYNC_BEGINx but with a custom |at| timestamp -// provided. -#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, id, \ - timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \ - category_group, name, id, timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val) -#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP2(category_group, name, id, \ - timestamp, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, id, \ - timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY) - -// Records a single ASYNC_STEP_INTO event for |step| immediately. If the -// category is not enabled, then this does nothing. The |name| and |id| must -// match the ASYNC_BEGIN event above. The |step| param identifies this step -// within the async event. This should be called at the beginning of the next -// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any -// ASYNC_STEP_PAST events. -#define TRACE_EVENT_ASYNC_STEP_INTO0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, "step", step) -#define TRACE_EVENT_ASYNC_STEP_INTO1(category_group, name, id, step, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val) - -// Similar to TRACE_EVENT_ASYNC_STEP_INTOx but with a custom |at| timestamp -// provided. -#define TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category_group, name, id, \ - step, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ - "step", step) - -// Records a single ASYNC_STEP_PAST event for |step| immediately. If the -// category is not enabled, then this does nothing. The |name| and |id| must -// match the ASYNC_BEGIN event above. The |step| param identifies this step -// within the async event. This should be called at the beginning of the next -// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any -// ASYNC_STEP_INTO events. -#define TRACE_EVENT_ASYNC_STEP_PAST0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, "step", step) -#define TRACE_EVENT_ASYNC_STEP_PAST1(category_group, name, id, step, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_ASYNC_STEP_PAST, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val) - -// Records a single ASYNC_END event for "name" immediately. If the category -// is not enabled, then this does nothing. -#define TRACE_EVENT_ASYNC_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_ASYNC_END2(category_group, name, id, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_ASYNC_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_ASYNC_END1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_ASYNC_END2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) - -// Similar to TRACE_EVENT_ASYNC_ENDx but with a custom |at| timestamp provided. -#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(category_group, name, id, \ - timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1(category_group, name, id, \ - timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val) -#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP2(category_group, name, id, \ - timestamp, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_ASYNC_END_WITH_TIMESTAMP0(category_group, name, id, \ - timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY) - -// NESTABLE_ASYNC_* APIs are used to describe an async operation, which can -// be nested within a NESTABLE_ASYNC event and/or have inner NESTABLE_ASYNC -// events. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - A pair of NESTABLE_ASYNC_BEGIN event and NESTABLE_ASYNC_END event is -// considered as a match if their category_group, name and id all match. -// - |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -// - |id| is used to match a child NESTABLE_ASYNC event with its parent -// NESTABLE_ASYNC event. Therefore, events in the same nested event tree must -// be logged using the same id and category_group. -// -// Unmatched NESTABLE_ASYNC_END event will be parsed as an event that starts -// at the first NESTABLE_ASYNC event of that id, and unmatched -// NESTABLE_ASYNC_BEGIN event will be parsed as an event that ends at the last -// NESTABLE_ASYNC event of that id. Corresponding warning messages for -// unmatched events will be shown in the analysis view. - -// Records a single NESTABLE_ASYNC_BEGIN event called "name" immediately, with -// 0, 1 or 2 associated arguments. If the category is not enabled, then this -// does nothing. -#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) -// Records a single NESTABLE_ASYNC_END event called "name" immediately, with 0 -// or 2 associated arguments. If the category is not enabled, then this does -// nothing. -#define TRACE_EVENT_NESTABLE_ASYNC_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) -// Records a single NESTABLE_ASYNC_END event called "name" immediately, with 1 -// associated argument. If the category is not enabled, then this does nothing. -#define TRACE_EVENT_NESTABLE_ASYNC_END1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_NESTABLE_ASYNC_END2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) - -// Records a single NESTABLE_ASYNC_INSTANT event called "name" immediately, -// with none, one or two associated argument. If the category is not enabled, -// then this does nothing. -#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) - -#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(category_group, name, id, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) - -#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT2( \ - category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) - -#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TTS2( \ - category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_FLAG_ASYNC_TTS | TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TTS2( \ - category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_FLAG_ASYNC_TTS | TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -// Similar to TRACE_EVENT_NESTABLE_ASYNC_{BEGIN,END}x but with a custom -// |timestamp| provided. -#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, \ - id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(category_group, name, \ - id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1( \ - category_group, name, id, timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val) -#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0( \ - category_group, name, id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( \ - category_group, name, id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( \ - category_group, name, id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY) - -// Records a single FLOW_BEGIN event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to match the FLOW_BEGIN event with the FLOW_END event. FLOW -// events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -// FLOW events are different from ASYNC events in how they are drawn by the -// tracing UI. A FLOW defines asynchronous data flow, such as posting a task -// (FLOW_BEGIN) and later executing that task (FLOW_END). Expect FLOWs to be -// drawn as lines or arrows from FLOW_BEGIN scopes to FLOW_END scopes. Similar -// to ASYNC, a FLOW can consist of multiple phases. The first phase is defined -// by the FLOW_BEGIN calls. Additional phases can be defined using the FLOW_STEP -// macros. When the operation completes, call FLOW_END. An async operation can -// span threads and processes, but all events in that operation must use the -// same |name| and |id|. Each event can have its own args. -#define TRACE_EVENT_FLOW_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_FLOW_BEGIN1(category_group, name, id, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_FLOW_BEGIN2(category_group, name, id, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_FLOW_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_FLOW_BEGIN1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_FLOW_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) - -// Records a single FLOW_STEP event for |step| immediately. If the category -// is not enabled, then this does nothing. The |name| and |id| must match the -// FLOW_BEGIN event above. The |step| param identifies this step within the -// async event. This should be called at the beginning of the next phase of an -// asynchronous operation. -#define TRACE_EVENT_FLOW_STEP0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, "step", step) -#define TRACE_EVENT_FLOW_STEP1(category_group, name, id, step, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_FLOW_STEP0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ - category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, "step", step) -#define TRACE_EVENT_COPY_FLOW_STEP1(category_group, name, id, step, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, id, \ - TRACE_EVENT_FLAG_COPY, "step", step, arg1_name, arg1_val) - -// Records a single FLOW_END event for "name" immediately. If the category -// is not enabled, then this does nothing. -#define TRACE_EVENT_FLOW_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \ - name, id, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \ - name, id, \ - TRACE_EVENT_FLAG_BIND_TO_ENCLOSING) -#define TRACE_EVENT_FLOW_END1(category_group, name, id, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \ - name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \ - arg1_val) -#define TRACE_EVENT_FLOW_END2(category_group, name, id, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \ - name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \ - arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_FLOW_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \ - name, id, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_FLOW_END1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \ - name, id, TRACE_EVENT_FLAG_COPY, arg1_name, \ - arg1_val) -#define TRACE_EVENT_COPY_FLOW_END2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \ - name, id, TRACE_EVENT_FLAG_COPY, arg1_name, \ - arg1_val, arg2_name, arg2_val) - -// Special trace event macro to trace task execution with the location where it -// was posted from. -#define TRACE_TASK_EXECUTION(run_function, task) \ - INTERNAL_TRACE_TASK_EXECUTION(run_function, task) - -// TRACE_EVENT_METADATA* events are information related to other -// injected events, not events in their own right. -#define TRACE_EVENT_METADATA1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_METADATA_ADD(category_group, name, arg1_name, arg1_val) - -// Records a clock sync event. -#define TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id) \ - INTERNAL_TRACE_EVENT_ADD( \ - TRACE_EVENT_PHASE_CLOCK_SYNC, "__metadata", "clock_sync", \ - TRACE_EVENT_FLAG_NONE, "sync_id", sync_id) -#define TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts) \ - INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ - TRACE_EVENT_PHASE_CLOCK_SYNC, "__metadata", "clock_sync", \ - issue_end_ts, TRACE_EVENT_FLAG_NONE, \ - "sync_id", sync_id, "issue_ts", issue_ts) - -// Macros to track the life time and value of arbitrary client objects. -// See also TraceTrackableObject. -#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_CREATE_OBJECT, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) - -#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \ - snapshot) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \ - id, TRACE_EVENT_FLAG_NONE, "snapshot", snapshot) - -#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP( \ - category_group, name, id, timestamp, snapshot) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \ - id, TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ - "snapshot", snapshot) - -#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_DELETE_OBJECT, category_group, name, id, \ - TRACE_EVENT_FLAG_NONE) - -// Records entering and leaving trace event contexts. |category_group| and -// |name| specify the context category and type. |context| is a -// snapshotted context object id. -#define TRACE_EVENT_ENTER_CONTEXT(category_group, name, context) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_ENTER_CONTEXT, category_group, name, context, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_LEAVE_CONTEXT(category_group, name, context) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ - TRACE_EVENT_PHASE_LEAVE_CONTEXT, category_group, name, context, \ - TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_SCOPED_CONTEXT(category_group, name, context) \ - INTERNAL_TRACE_EVENT_SCOPED_CONTEXT(category_group, name, context) - -// Macro to specify that two trace IDs are identical. For example, -// TRACE_LINK_IDS( -// "category", "name", -// TRACE_ID_WITH_SCOPE("net::URLRequest", 0x1000), -// TRACE_ID_WITH_SCOPE("blink::ResourceFetcher::FetchRequest", 0x2000)) -// tells the trace consumer that events with ID ("net::URLRequest", 0x1000) from -// the current process have the same ID as events with ID -// ("blink::ResourceFetcher::FetchRequest", 0x2000). -#define TRACE_LINK_IDS(category_group, name, id, linked_id) \ - INTERNAL_TRACE_EVENT_ADD_LINK_IDS(category_group, name, id, linked_id); - -// Macro to efficiently determine if a given category group is enabled. -#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - *ret = true; \ - } else { \ - *ret = false; \ - } \ - } while (0) - -// Macro to explicitly warm up a given category group. This could be useful in -// cases where we want to initialize a category group before any trace events -// for that category group is reported. For example, to have a category group -// always show up in the "record categories" list for manually selecting -// settings in about://tracing. -#define TRACE_EVENT_WARMUP_CATEGORY(category_group) \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) - -// Macro to efficiently determine, through polling, if a new trace has begun. -#define TRACE_EVENT_IS_NEW_TRACE(ret) \ - do { \ - static int INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = 0; \ - int num_traces_recorded = TRACE_EVENT_API_GET_NUM_TRACES_RECORDED(); \ - if (num_traces_recorded != -1 && \ - num_traces_recorded != \ - INTERNAL_TRACE_EVENT_UID(lastRecordingNumber)) { \ - INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = num_traces_recorded; \ - *ret = true; \ - } else { \ - *ret = false; \ - } \ - } while (0) - -// Macro for getting the real base::TimeTicks::Now() which can be overridden in -// headless when VirtualTime is enabled. -#define TRACE_TIME_TICKS_NOW() INTERNAL_TRACE_TIME_TICKS_NOW() - -// Macro for getting the real base::Time::Now() which can be overridden in -// headless when VirtualTime is enabled. -#define TRACE_TIME_NOW() INTERNAL_TRACE_TIME_NOW() - -// Notes regarding the following definitions: -// New values can be added and propagated to third party libraries, but existing -// definitions must never be changed, because third party libraries may use old -// definitions. - -// Phase indicates the nature of an event entry. E.g. part of a begin/end pair. -#define TRACE_EVENT_PHASE_BEGIN ('B') -#define TRACE_EVENT_PHASE_END ('E') -#define TRACE_EVENT_PHASE_COMPLETE ('X') -#define TRACE_EVENT_PHASE_INSTANT ('I') -#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') -#define TRACE_EVENT_PHASE_ASYNC_STEP_INTO ('T') -#define TRACE_EVENT_PHASE_ASYNC_STEP_PAST ('p') -#define TRACE_EVENT_PHASE_ASYNC_END ('F') -#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN ('b') -#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_END ('e') -#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT ('n') -#define TRACE_EVENT_PHASE_FLOW_BEGIN ('s') -#define TRACE_EVENT_PHASE_FLOW_STEP ('t') -#define TRACE_EVENT_PHASE_FLOW_END ('f') -#define TRACE_EVENT_PHASE_METADATA ('M') -#define TRACE_EVENT_PHASE_COUNTER ('C') -#define TRACE_EVENT_PHASE_SAMPLE ('P') -#define TRACE_EVENT_PHASE_CREATE_OBJECT ('N') -#define TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ('O') -#define TRACE_EVENT_PHASE_DELETE_OBJECT ('D') -#define TRACE_EVENT_PHASE_MEMORY_DUMP ('v') -#define TRACE_EVENT_PHASE_MARK ('R') -#define TRACE_EVENT_PHASE_CLOCK_SYNC ('c') -#define TRACE_EVENT_PHASE_ENTER_CONTEXT ('(') -#define TRACE_EVENT_PHASE_LEAVE_CONTEXT (')') -#define TRACE_EVENT_PHASE_LINK_IDS ('=') - -// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. -#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0)) -#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned int>(1 << 0)) -#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned int>(1 << 1)) -// TODO(crbug.com/639003): Free this bit after ID mangling is deprecated. -#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned int>(1 << 2)) -#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned int>(1 << 3)) -#define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast<unsigned int>(1 << 4)) -#define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast<unsigned int>(1 << 5)) -#define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast<unsigned int>(1 << 6)) -#define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast<unsigned int>(1 << 7)) -#define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8)) -#define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9)) -#define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10)) -#define TRACE_EVENT_FLAG_HAS_PROCESS_ID (static_cast<unsigned int>(1 << 11)) -#define TRACE_EVENT_FLAG_HAS_LOCAL_ID (static_cast<unsigned int>(1 << 12)) -#define TRACE_EVENT_FLAG_HAS_GLOBAL_ID (static_cast<unsigned int>(1 << 13)) - -#define TRACE_EVENT_FLAG_SCOPE_MASK \ - (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \ - TRACE_EVENT_FLAG_SCOPE_EXTRA)) - -// Type values for identifying types in the TraceValue union. -#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1)) -#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2)) -#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3)) -#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4)) -#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5)) -#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6)) -#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7)) -#define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8)) - -// Enum reflecting the scope of an INSTANT event. Must fit within -// TRACE_EVENT_FLAG_SCOPE_MASK. -#define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3)) -#define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3)) -#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3)) - -#define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g') -#define TRACE_EVENT_SCOPE_NAME_PROCESS ('p') -#define TRACE_EVENT_SCOPE_NAME_THREAD ('t') - -#endif // BASE_TRACE_EVENT_COMMON_TRACE_EVENT_COMMON_H_
diff --git a/base/trace_event/etw_manifest/chrome_events_win.man b/base/trace_event/etw_manifest/chrome_events_win.man deleted file mode 100644 index 10a8ddf..0000000 --- a/base/trace_event/etw_manifest/chrome_events_win.man +++ /dev/null
@@ -1,84 +0,0 @@ -<?xml version='1.0' encoding='utf-8' standalone='yes'?> -<instrumentationManifest - xmlns="http://schemas.microsoft.com/win/2004/08/events" - xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" - xmlns:xs="http://www.w3.org/2001/XMLSchema" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd" - > - <instrumentation> - <events> - <provider - guid="{D2D578D9-2936-45B6-A09f-30E32715F42D}" - messageFileName="chrome.dll" - name="Chrome" - resourceFileName="chrome.dll" - symbol="CHROME" - > - <channels> - <importChannel - chid="SYSTEM" - name="System" - /> - </channels> - <templates> - <template tid="tid_chrome_event"> - <data - inType="win:AnsiString" - name="Name" - /> - <data - inType="win:AnsiString" - name="Phase" - /> - <data - inType="win:AnsiString" - name="Arg Name 1" - /> - <data - inType="win:AnsiString" - name="Arg Value 1" - /> - <data - inType="win:AnsiString" - name="Arg Name 2" - /> - <data - inType="win:AnsiString" - name="Arg Value 2" - /> - <data - inType="win:AnsiString" - name="Arg Name 3" - /> - <data - inType="win:AnsiString" - name="Arg Value 3" - /> - </template> - </templates> - <events> - <event - channel="SYSTEM" - level="win:Informational" - message="$(string.ChromeEvent.EventMessage)" - opcode="win:Info" - symbol="ChromeEvent" - template="tid_chrome_event" - value="1" - /> - </events> - </provider> - </events> - </instrumentation> - <localization xmlns="http://schemas.microsoft.com/win/2004/08/events"> - <resources culture="en-US"> - <stringTable> - <string - id="ChromeEvent.EventMessage" - value="Chrome Event: %1 (%2)" - /> - </stringTable> - </resources> - </localization> -</instrumentationManifest>
diff --git a/base/trace_event/event_name_filter.cc b/base/trace_event/event_name_filter.cc deleted file mode 100644 index 7bf932e..0000000 --- a/base/trace_event/event_name_filter.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/event_name_filter.h" - -#include "base/trace_event/trace_event_impl.h" - -namespace base { -namespace trace_event { - -// static -const char EventNameFilter::kName[] = "event_whitelist_predicate"; - -EventNameFilter::EventNameFilter( - std::unique_ptr<EventNamesWhitelist> event_names_whitelist) - : event_names_whitelist_(std::move(event_names_whitelist)) {} - -EventNameFilter::~EventNameFilter() = default; - -bool EventNameFilter::FilterTraceEvent(const TraceEvent& trace_event) const { - return event_names_whitelist_->count(trace_event.name()) != 0; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/event_name_filter.h b/base/trace_event/event_name_filter.h deleted file mode 100644 index 19333b3..0000000 --- a/base/trace_event/event_name_filter.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_EVENT_NAME_FILTER_H_ -#define BASE_TRACE_EVENT_EVENT_NAME_FILTER_H_ - -#include <memory> -#include <string> -#include <unordered_set> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/trace_event/trace_event_filter.h" - -namespace base { -namespace trace_event { - -class TraceEvent; - -// Filters trace events by checking the full name against a whitelist. -// The current implementation is quite simple and dumb and just uses a -// hashtable which requires char* to std::string conversion. It could be smarter -// and use a bloom filter trie. However, today this is used too rarely to -// justify that cost. -class BASE_EXPORT EventNameFilter : public TraceEventFilter { - public: - using EventNamesWhitelist = std::unordered_set<std::string>; - static const char kName[]; - - EventNameFilter(std::unique_ptr<EventNamesWhitelist>); - ~EventNameFilter() override; - - // TraceEventFilter implementation. - bool FilterTraceEvent(const TraceEvent&) const override; - - private: - std::unique_ptr<const EventNamesWhitelist> event_names_whitelist_; - - DISALLOW_COPY_AND_ASSIGN(EventNameFilter); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_EVENT_NAME_FILTER_H_
diff --git a/base/trace_event/heap_profiler.h b/base/trace_event/heap_profiler.h deleted file mode 100644 index c8deaf6..0000000 --- a/base/trace_event/heap_profiler.h +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_H -#define BASE_TRACE_EVENT_HEAP_PROFILER_H - -#include "base/compiler_specific.h" -#include "base/trace_event/heap_profiler_allocation_context_tracker.h" - -// This header file defines the set of macros that are used to track memory -// usage in the heap profiler. This is in addition to the macros defined in -// trace_event.h and are specific to heap profiler. This file also defines -// implementation details of these macros. - -// Implementation detail: heap profiler macros create temporary variables to -// keep instrumentation overhead low. These macros give each temporary variable -// a unique name based on the line number to prevent name collisions. -#define INTERNAL_HEAP_PROFILER_UID3(a, b) heap_profiler_unique_##a##b -#define INTERNAL_HEAP_PROFILER_UID2(a, b) INTERNAL_HEAP_PROFILER_UID3(a, b) -#define INTERNAL_HEAP_PROFILER_UID(name_prefix) \ - INTERNAL_HEAP_PROFILER_UID2(name_prefix, __LINE__) - -// Scoped tracker for task execution context in the heap profiler. -#define TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION \ - trace_event_internal::HeapProfilerScopedTaskExecutionTracker - -// Scoped tracker that tracks the given program counter as a native stack frame -// in the heap profiler. -#define TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER \ - trace_event_internal::HeapProfilerScopedStackFrame - -// A scoped ignore event used to tell heap profiler to ignore all the -// allocations in the scope. It is useful to exclude allocations made for -// tracing from the heap profiler dumps. -#define HEAP_PROFILER_SCOPED_IGNORE \ - trace_event_internal::HeapProfilerScopedIgnore INTERNAL_HEAP_PROFILER_UID( \ - scoped_ignore) - -namespace trace_event_internal { - -// HeapProfilerScopedTaskExecutionTracker records the current task's context in -// the heap profiler. -class HeapProfilerScopedTaskExecutionTracker { - public: - inline explicit HeapProfilerScopedTaskExecutionTracker( - const char* task_context) - : context_(task_context) { - using base::trace_event::AllocationContextTracker; - if (UNLIKELY(AllocationContextTracker::capture_mode() != - AllocationContextTracker::CaptureMode::DISABLED)) { - AllocationContextTracker::GetInstanceForCurrentThread() - ->PushCurrentTaskContext(context_); - } - } - - inline ~HeapProfilerScopedTaskExecutionTracker() { - using base::trace_event::AllocationContextTracker; - if (UNLIKELY(AllocationContextTracker::capture_mode() != - AllocationContextTracker::CaptureMode::DISABLED)) { - AllocationContextTracker::GetInstanceForCurrentThread() - ->PopCurrentTaskContext(context_); - } - } - - private: - const char* context_; -}; - -class HeapProfilerScopedStackFrame { - public: - inline explicit HeapProfilerScopedStackFrame(const void* program_counter) - : program_counter_(program_counter) { - using base::trace_event::AllocationContextTracker; - if (UNLIKELY(AllocationContextTracker::capture_mode() == - AllocationContextTracker::CaptureMode::MIXED_STACK)) { - AllocationContextTracker::GetInstanceForCurrentThread() - ->PushNativeStackFrame(program_counter_); - } - } - - inline ~HeapProfilerScopedStackFrame() { - using base::trace_event::AllocationContextTracker; - if (UNLIKELY(AllocationContextTracker::capture_mode() == - AllocationContextTracker::CaptureMode::MIXED_STACK)) { - AllocationContextTracker::GetInstanceForCurrentThread() - ->PopNativeStackFrame(program_counter_); - } - } - - private: - const void* const program_counter_; -}; - -class BASE_EXPORT HeapProfilerScopedIgnore { - public: - inline HeapProfilerScopedIgnore() { - using base::trace_event::AllocationContextTracker; - if (UNLIKELY( - AllocationContextTracker::capture_mode() != - AllocationContextTracker::CaptureMode::DISABLED)) { - AllocationContextTracker::GetInstanceForCurrentThread() - ->begin_ignore_scope(); - } - } - inline ~HeapProfilerScopedIgnore() { - using base::trace_event::AllocationContextTracker; - if (UNLIKELY( - AllocationContextTracker::capture_mode() != - AllocationContextTracker::CaptureMode::DISABLED)) { - AllocationContextTracker::GetInstanceForCurrentThread() - ->end_ignore_scope(); - } - } -}; - -} // namespace trace_event_internal - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_H
diff --git a/base/trace_event/heap_profiler_allocation_context.cc b/base/trace_event/heap_profiler_allocation_context.cc deleted file mode 100644 index bdc3c58..0000000 --- a/base/trace_event/heap_profiler_allocation_context.cc +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/heap_profiler_allocation_context.h" - -#include <cstring> - -#include "base/hash.h" -#include "base/macros.h" - -namespace base { -namespace trace_event { - -bool operator < (const StackFrame& lhs, const StackFrame& rhs) { - return lhs.value < rhs.value; -} - -bool operator == (const StackFrame& lhs, const StackFrame& rhs) { - return lhs.value == rhs.value; -} - -bool operator != (const StackFrame& lhs, const StackFrame& rhs) { - return !(lhs.value == rhs.value); -} - -Backtrace::Backtrace() = default; - -bool operator==(const Backtrace& lhs, const Backtrace& rhs) { - if (lhs.frame_count != rhs.frame_count) return false; - return std::equal(lhs.frames, lhs.frames + lhs.frame_count, rhs.frames); -} - -bool operator!=(const Backtrace& lhs, const Backtrace& rhs) { - return !(lhs == rhs); -} - -AllocationContext::AllocationContext(): type_name(nullptr) {} - -AllocationContext::AllocationContext(const Backtrace& backtrace, - const char* type_name) - : backtrace(backtrace), type_name(type_name) {} - -bool operator==(const AllocationContext& lhs, const AllocationContext& rhs) { - return (lhs.backtrace == rhs.backtrace) && (lhs.type_name == rhs.type_name); -} - -bool operator!=(const AllocationContext& lhs, const AllocationContext& rhs) { - return !(lhs == rhs); -} - -} // namespace trace_event -} // namespace base - -namespace std { - -using base::trace_event::AllocationContext; -using base::trace_event::Backtrace; -using base::trace_event::StackFrame; - -size_t hash<StackFrame>::operator()(const StackFrame& frame) const { - return hash<const void*>()(frame.value); -} - -size_t hash<Backtrace>::operator()(const Backtrace& backtrace) const { - const void* values[Backtrace::kMaxFrameCount]; - for (size_t i = 0; i != backtrace.frame_count; ++i) { - values[i] = backtrace.frames[i].value; - } - return base::PersistentHash(values, backtrace.frame_count * sizeof(*values)); -} - -size_t hash<AllocationContext>::operator()(const AllocationContext& ctx) const { - size_t backtrace_hash = hash<Backtrace>()(ctx.backtrace); - - // Multiplicative hash from [Knuth 1998]. Works best if |size_t| is 32 bits, - // because the magic number is a prime very close to 2^32 / golden ratio, but - // will still redistribute keys bijectively on 64-bit architectures because - // the magic number is coprime to 2^64. - size_t type_hash = reinterpret_cast<size_t>(ctx.type_name) * 2654435761; - - // Multiply one side to break the commutativity of +. Multiplication with a - // number coprime to |numeric_limits<size_t>::max() + 1| is bijective so - // randomness is preserved. - return (backtrace_hash * 3) + type_hash; -} - -} // namespace std
diff --git a/base/trace_event/heap_profiler_allocation_context.h b/base/trace_event/heap_profiler_allocation_context.h deleted file mode 100644 index c35663f..0000000 --- a/base/trace_event/heap_profiler_allocation_context.h +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ -#define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <functional> - -#include "base/base_export.h" - -namespace base { -namespace trace_event { - -// When heap profiling is enabled, tracing keeps track of the allocation -// context for each allocation intercepted. It is generated by the -// |AllocationContextTracker| which keeps stacks of context in TLS. -// The tracker is initialized lazily. - -// The backtrace in the allocation context is a snapshot of the stack. For now, -// this is the pseudo stack where frames are created by trace event macros. In -// the future, we might add the option to use the native call stack. In that -// case, |Backtrace| and |AllocationContextTracker::GetContextSnapshot| might -// have different implementations that can be selected by a compile time flag. - -// The number of stack frames stored in the backtrace is a trade off between -// memory used for tracing and accuracy. Measurements done on a prototype -// revealed that: -// -// - In 60 percent of the cases, pseudo stack depth <= 7. -// - In 87 percent of the cases, pseudo stack depth <= 9. -// - In 95 percent of the cases, pseudo stack depth <= 11. -// -// See the design doc (https://goo.gl/4s7v7b) for more details. - -// Represents (pseudo) stack frame. Used in Backtrace class below. -// -// Conceptually stack frame is identified by its value, and type is used -// mostly to properly format the value. Value is expected to be a valid -// pointer from process' address space. -struct BASE_EXPORT StackFrame { - enum class Type { - TRACE_EVENT_NAME, // const char* string - THREAD_NAME, // const char* thread name - PROGRAM_COUNTER, // as returned by stack tracing (e.g. by StackTrace) - }; - - static StackFrame FromTraceEventName(const char* name) { - return {Type::TRACE_EVENT_NAME, name}; - } - static StackFrame FromThreadName(const char* name) { - return {Type::THREAD_NAME, name}; - } - static StackFrame FromProgramCounter(const void* pc) { - return {Type::PROGRAM_COUNTER, pc}; - } - - Type type; - const void* value; -}; - -bool BASE_EXPORT operator < (const StackFrame& lhs, const StackFrame& rhs); -bool BASE_EXPORT operator == (const StackFrame& lhs, const StackFrame& rhs); -bool BASE_EXPORT operator != (const StackFrame& lhs, const StackFrame& rhs); - -struct BASE_EXPORT Backtrace { - Backtrace(); - - // If the stack is higher than what can be stored here, the top frames - // (the ones further from main()) are stored. Depth of 12 is enough for most - // pseudo traces (see above), but not for native traces, where we need more. - enum { kMaxFrameCount = 48 }; - StackFrame frames[kMaxFrameCount]; - size_t frame_count = 0; -}; - -bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs); -bool BASE_EXPORT operator!=(const Backtrace& lhs, const Backtrace& rhs); - -// The |AllocationContext| is context metadata that is kept for every allocation -// when heap profiling is enabled. To simplify memory management for book- -// keeping, this struct has a fixed size. -struct BASE_EXPORT AllocationContext { - AllocationContext(); - AllocationContext(const Backtrace& backtrace, const char* type_name); - - Backtrace backtrace; - - // Type name of the type stored in the allocated memory. A null pointer - // indicates "unknown type". Grouping is done by comparing pointers, not by - // deep string comparison. In a component build, where a type name can have a - // string literal in several dynamic libraries, this may distort grouping. - const char* type_name; -}; - -bool BASE_EXPORT operator==(const AllocationContext& lhs, - const AllocationContext& rhs); -bool BASE_EXPORT operator!=(const AllocationContext& lhs, - const AllocationContext& rhs); - -// Struct to store the size and count of the allocations. -struct AllocationMetrics { - size_t size; - size_t count; -}; - -} // namespace trace_event -} // namespace base - -namespace std { - -template <> -struct BASE_EXPORT hash<base::trace_event::StackFrame> { - size_t operator()(const base::trace_event::StackFrame& frame) const; -}; - -template <> -struct BASE_EXPORT hash<base::trace_event::Backtrace> { - size_t operator()(const base::trace_event::Backtrace& backtrace) const; -}; - -template <> -struct BASE_EXPORT hash<base::trace_event::AllocationContext> { - size_t operator()(const base::trace_event::AllocationContext& context) const; -}; - -} // namespace std - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc deleted file mode 100644 index 526eac8..0000000 --- a/base/trace_event/heap_profiler_allocation_context_tracker.cc +++ /dev/null
@@ -1,253 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/heap_profiler_allocation_context_tracker.h" - -#include <algorithm> -#include <iterator> - -#include "base/atomicops.h" -#include "base/debug/leak_annotations.h" -#include "base/debug/stack_trace.h" -#include "base/no_destructor.h" -#include "base/threading/platform_thread.h" -#include "base/threading/thread_local_storage.h" -#include "base/trace_event/heap_profiler_allocation_context.h" -#include "build_config.h" - -#if defined(OS_LINUX) || defined(OS_ANDROID) -#include <sys/prctl.h> -#endif - -namespace base { -namespace trace_event { - -subtle::Atomic32 AllocationContextTracker::capture_mode_ = - static_cast<int32_t>(AllocationContextTracker::CaptureMode::DISABLED); - -namespace { - -const size_t kMaxStackDepth = 128u; -const size_t kMaxTaskDepth = 16u; -AllocationContextTracker* const kInitializingSentinel = - reinterpret_cast<AllocationContextTracker*>(-1); - -// This function is added to the TLS slot to clean up the instance when the -// thread exits. -void DestructAllocationContextTracker(void* alloc_ctx_tracker) { - delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker); -} - -ThreadLocalStorage::Slot& AllocationContextTrackerTLS() { - static NoDestructor<ThreadLocalStorage::Slot> tls_alloc_ctx_tracker( - &DestructAllocationContextTracker); - return *tls_alloc_ctx_tracker; -} - -// Cannot call ThreadIdNameManager::GetName because it holds a lock and causes -// deadlock when lock is already held by ThreadIdNameManager before the current -// allocation. Gets the thread name from kernel if available or returns a string -// with id. This function intentionally leaks the allocated strings since they -// are used to tag allocations even after the thread dies. -const char* GetAndLeakThreadName() { - char name[16]; -#if defined(OS_LINUX) || defined(OS_ANDROID) - // If the thread name is not set, try to get it from prctl. Thread name might - // not be set in cases where the thread started before heap profiling was - // enabled. - int err = prctl(PR_GET_NAME, name); - if (!err) { - return strdup(name); - } -#endif // defined(OS_LINUX) || defined(OS_ANDROID) - - // Use tid if we don't have a thread name. - snprintf(name, sizeof(name), "%lu", - static_cast<unsigned long>(PlatformThread::CurrentId())); - return strdup(name); -} - -} // namespace - -// static -AllocationContextTracker* -AllocationContextTracker::GetInstanceForCurrentThread() { - AllocationContextTracker* tracker = static_cast<AllocationContextTracker*>( - AllocationContextTrackerTLS().Get()); - if (tracker == kInitializingSentinel) - return nullptr; // Re-entrancy case. - - if (!tracker) { - AllocationContextTrackerTLS().Set(kInitializingSentinel); - tracker = new AllocationContextTracker(); - AllocationContextTrackerTLS().Set(tracker); - } - - return tracker; -} - -AllocationContextTracker::AllocationContextTracker() - : thread_name_(nullptr), ignore_scope_depth_(0) { - tracked_stack_.reserve(kMaxStackDepth); - task_contexts_.reserve(kMaxTaskDepth); -} -AllocationContextTracker::~AllocationContextTracker() = default; - -// static -void AllocationContextTracker::SetCurrentThreadName(const char* name) { - if (name && capture_mode() != CaptureMode::DISABLED) { - GetInstanceForCurrentThread()->thread_name_ = name; - } -} - -// static -void AllocationContextTracker::SetCaptureMode(CaptureMode mode) { - // Release ordering ensures that when a thread observes |capture_mode_| to - // be true through an acquire load, the TLS slot has been initialized. - subtle::Release_Store(&capture_mode_, static_cast<int32_t>(mode)); -} - -void AllocationContextTracker::PushPseudoStackFrame( - AllocationContextTracker::PseudoStackFrame stack_frame) { - // Impose a limit on the height to verify that every push is popped, because - // in practice the pseudo stack never grows higher than ~20 frames. - if (tracked_stack_.size() < kMaxStackDepth) { - tracked_stack_.push_back( - StackFrame::FromTraceEventName(stack_frame.trace_event_name)); - } else { - NOTREACHED(); - } -} - -void AllocationContextTracker::PopPseudoStackFrame( - AllocationContextTracker::PseudoStackFrame stack_frame) { - // Guard for stack underflow. If tracing was started with a TRACE_EVENT in - // scope, the frame was never pushed, so it is possible that pop is called - // on an empty stack. - if (tracked_stack_.empty()) - return; - - tracked_stack_.pop_back(); -} - -void AllocationContextTracker::PushNativeStackFrame(const void* pc) { - if (tracked_stack_.size() < kMaxStackDepth) - tracked_stack_.push_back(StackFrame::FromProgramCounter(pc)); - else - NOTREACHED(); -} - -void AllocationContextTracker::PopNativeStackFrame(const void* pc) { - if (tracked_stack_.empty()) - return; - - DCHECK_EQ(pc, tracked_stack_.back().value); - tracked_stack_.pop_back(); -} - -void AllocationContextTracker::PushCurrentTaskContext(const char* context) { - DCHECK(context); - if (task_contexts_.size() < kMaxTaskDepth) - task_contexts_.push_back(context); - else - NOTREACHED(); -} - -void AllocationContextTracker::PopCurrentTaskContext(const char* context) { - // Guard for stack underflow. If tracing was started with a TRACE_EVENT in - // scope, the context was never pushed, so it is possible that pop is called - // on an empty stack. - if (task_contexts_.empty()) - return; - - DCHECK_EQ(context, task_contexts_.back()) - << "Encountered an unmatched context end"; - task_contexts_.pop_back(); -} - -bool AllocationContextTracker::GetContextSnapshot(AllocationContext* ctx) { - if (ignore_scope_depth_) - return false; - - CaptureMode mode = static_cast<CaptureMode>( - subtle::NoBarrier_Load(&capture_mode_)); - - auto* backtrace = std::begin(ctx->backtrace.frames); - auto* backtrace_end = std::end(ctx->backtrace.frames); - - if (!thread_name_) { - // Ignore the string allocation made by GetAndLeakThreadName to avoid - // reentrancy. - ignore_scope_depth_++; - thread_name_ = GetAndLeakThreadName(); - ANNOTATE_LEAKING_OBJECT_PTR(thread_name_); - DCHECK(thread_name_); - ignore_scope_depth_--; - } - - // Add the thread name as the first entry in pseudo stack. - if (thread_name_) { - *backtrace++ = StackFrame::FromThreadName(thread_name_); - } - - switch (mode) { - case CaptureMode::DISABLED: - { - break; - } - case CaptureMode::PSEUDO_STACK: - case CaptureMode::MIXED_STACK: - { - for (const StackFrame& stack_frame : tracked_stack_) { - if (backtrace == backtrace_end) - break; - *backtrace++ = stack_frame; - } - break; - } - case CaptureMode::NATIVE_STACK: - { -// Backtrace contract requires us to return bottom frames, i.e. -// from main() and up. Stack unwinding produces top frames, i.e. -// from this point and up until main(). We intentionally request -// kMaxFrameCount + 1 frames, so that we know if there are more frames -// than our backtrace capacity. -#if !defined(OS_NACL) // We don't build base/debug/stack_trace.cc for NaCl. - // Fall-back to capturing the stack with base::debug::StackTrace, - // which is likely slower, but more reliable. - base::debug::StackTrace stack_trace(Backtrace::kMaxFrameCount + 1); - size_t frame_count = 0u; - const void* const* frames = stack_trace.Addresses(&frame_count); - - // If there are too many frames, keep the ones furthest from main(). - size_t backtrace_capacity = backtrace_end - backtrace; - int32_t starting_frame_index = frame_count; - if (frame_count > backtrace_capacity) { - starting_frame_index = backtrace_capacity - 1; - *backtrace++ = StackFrame::FromTraceEventName("<truncated>"); - } - for (int32_t i = starting_frame_index - 1; i >= 0; --i) { - const void* frame = frames[i]; - *backtrace++ = StackFrame::FromProgramCounter(frame); - } -#endif // !defined(OS_NACL) - break; - } - } - - ctx->backtrace.frame_count = backtrace - std::begin(ctx->backtrace.frames); - - // TODO(ssid): Fix crbug.com/594803 to add file name as 3rd dimension - // (component name) in the heap profiler and not piggy back on the type name. - if (!task_contexts_.empty()) { - ctx->type_name = task_contexts_.back(); - } else { - ctx->type_name = nullptr; - } - - return true; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.h b/base/trace_event/heap_profiler_allocation_context_tracker.h deleted file mode 100644 index da03b7f..0000000 --- a/base/trace_event/heap_profiler_allocation_context_tracker.h +++ /dev/null
@@ -1,140 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ -#define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ - -#include <vector> - -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/macros.h" -#include "base/trace_event/heap_profiler_allocation_context.h" - -namespace base { -namespace trace_event { - -// AllocationContextTracker is a thread-local object. Its main purpose is to -// keep track of a pseudo stack of trace events. Chrome has been instrumented -// with lots of `TRACE_EVENT` macros. These trace events push their name to a -// thread-local stack when they go into scope, and pop when they go out of -// scope, if all of the following conditions have been met: -// -// * A trace is being recorded. -// * The category of the event is enabled in the trace config. -// * Heap profiling is enabled (with the `--enable-heap-profiling` flag). -// -// This means that allocations that occur before tracing is started will not -// have backtrace information in their context. -// -// AllocationContextTracker also keeps track of some thread state not related to -// trace events. See |AllocationContext|. -// -// A thread-local instance of the context tracker is initialized lazily when it -// is first accessed. This might be because a trace event pushed or popped, or -// because `GetContextSnapshot()` was called when an allocation occurred -class BASE_EXPORT AllocationContextTracker { - public: - enum class CaptureMode : int32_t { - DISABLED, // Don't capture anything - PSEUDO_STACK, // Backtrace has trace events - MIXED_STACK, // Backtrace has trace events + from - // HeapProfilerScopedStackFrame - NATIVE_STACK, // Backtrace has full native backtraces from stack unwinding - }; - - // Stack frame constructed from trace events in codebase. - struct BASE_EXPORT PseudoStackFrame { - const char* trace_event_category; - const char* trace_event_name; - - bool operator==(const PseudoStackFrame& other) const { - return trace_event_category == other.trace_event_category && - trace_event_name == other.trace_event_name; - } - }; - - // Globally sets capturing mode. - // TODO(primiano): How to guard against *_STACK -> DISABLED -> *_STACK? - static void SetCaptureMode(CaptureMode mode); - - // Returns global capturing mode. - inline static CaptureMode capture_mode() { - // A little lag after heap profiling is enabled or disabled is fine, it is - // more important that the check is as cheap as possible when capturing is - // not enabled, so do not issue a memory barrier in the fast path. - if (subtle::NoBarrier_Load(&capture_mode_) == - static_cast<int32_t>(CaptureMode::DISABLED)) - return CaptureMode::DISABLED; - - // In the slow path, an acquire load is required to pair with the release - // store in |SetCaptureMode|. This is to ensure that the TLS slot for - // the thread-local allocation context tracker has been initialized if - // |capture_mode| returns something other than DISABLED. - return static_cast<CaptureMode>(subtle::Acquire_Load(&capture_mode_)); - } - - // Returns the thread-local instance, creating one if necessary. Returns - // always a valid instance, unless it is called re-entrantly, in which case - // returns nullptr in the nested calls. - static AllocationContextTracker* GetInstanceForCurrentThread(); - - // Set the thread name in the AllocationContextTracker of the current thread - // if capture is enabled. - static void SetCurrentThreadName(const char* name); - - // Starts and ends a new ignore scope between which the allocations are - // ignored by the heap profiler. GetContextSnapshot() returns false when - // allocations are ignored. - void begin_ignore_scope() { ignore_scope_depth_++; } - void end_ignore_scope() { - if (ignore_scope_depth_) - ignore_scope_depth_--; - } - - // Pushes and pops a frame onto the thread-local pseudo stack. - // TODO(ssid): Change PseudoStackFrame to const char*. Only event name is - // used. - void PushPseudoStackFrame(PseudoStackFrame stack_frame); - void PopPseudoStackFrame(PseudoStackFrame stack_frame); - - // Pushes and pops a native stack frame onto thread local tracked stack. - void PushNativeStackFrame(const void* pc); - void PopNativeStackFrame(const void* pc); - - // Push and pop current task's context. A stack is used to support nested - // tasks and the top of the stack will be used in allocation context. - void PushCurrentTaskContext(const char* context); - void PopCurrentTaskContext(const char* context); - - // Fills a snapshot of the current thread-local context. Doesn't fill and - // returns false if allocations are being ignored. - bool GetContextSnapshot(AllocationContext* snapshot); - - ~AllocationContextTracker(); - - private: - AllocationContextTracker(); - - static subtle::Atomic32 capture_mode_; - - // The pseudo stack where frames are |TRACE_EVENT| names or inserted PCs. - std::vector<StackFrame> tracked_stack_; - - // The thread name is used as the first entry in the pseudo stack. - const char* thread_name_; - - // Stack of tasks' contexts. Context serves as a different dimension than - // pseudo stack to cluster allocations. - std::vector<const char*> task_contexts_; - - uint32_t ignore_scope_depth_; - - DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_
diff --git a/base/trace_event/heap_profiler_event_filter.cc b/base/trace_event/heap_profiler_event_filter.cc deleted file mode 100644 index 937072c..0000000 --- a/base/trace_event/heap_profiler_event_filter.cc +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/heap_profiler_event_filter.h" - -#include "base/trace_event/category_registry.h" -#include "base/trace_event/heap_profiler_allocation_context_tracker.h" -#include "base/trace_event/trace_category.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_impl.h" - -namespace base { -namespace trace_event { - -namespace { - -inline bool IsPseudoStackEnabled() { - // Only PSEUDO_STACK and MIXED_STACK modes require trace events. - return AllocationContextTracker::capture_mode() == - AllocationContextTracker::CaptureMode::PSEUDO_STACK || - AllocationContextTracker::capture_mode() == - AllocationContextTracker::CaptureMode::MIXED_STACK; -} - -inline AllocationContextTracker* GetThreadLocalTracker() { - return AllocationContextTracker::GetInstanceForCurrentThread(); -} - -} // namespace - -// static -const char HeapProfilerEventFilter::kName[] = "heap_profiler_predicate"; - -HeapProfilerEventFilter::HeapProfilerEventFilter() = default; -HeapProfilerEventFilter::~HeapProfilerEventFilter() = default; - -bool HeapProfilerEventFilter::FilterTraceEvent( - const TraceEvent& trace_event) const { - if (!IsPseudoStackEnabled()) - return true; - - // TODO(primiano): Add support for events with copied name crbug.com/581079. - if (trace_event.flags() & TRACE_EVENT_FLAG_COPY) - return true; - - const auto* category = CategoryRegistry::GetCategoryByStatePtr( - trace_event.category_group_enabled()); - AllocationContextTracker::PseudoStackFrame frame = {category->name(), - trace_event.name()}; - if (trace_event.phase() == TRACE_EVENT_PHASE_BEGIN || - trace_event.phase() == TRACE_EVENT_PHASE_COMPLETE) { - GetThreadLocalTracker()->PushPseudoStackFrame(frame); - } else if (trace_event.phase() == TRACE_EVENT_PHASE_END) { - // The pop for |TRACE_EVENT_PHASE_COMPLETE| events is in |EndEvent|. - GetThreadLocalTracker()->PopPseudoStackFrame(frame); - } - // Do not filter-out any events and always return true. TraceLog adds the - // event only if it is enabled for recording. - return true; -} - -void HeapProfilerEventFilter::EndEvent(const char* category_name, - const char* event_name) const { - if (IsPseudoStackEnabled()) - GetThreadLocalTracker()->PopPseudoStackFrame({category_name, event_name}); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/heap_profiler_event_filter.h b/base/trace_event/heap_profiler_event_filter.h deleted file mode 100644 index 47368a1..0000000 --- a/base/trace_event/heap_profiler_event_filter.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_EVENT_FILTER_H_ -#define BASE_TRACE_EVENT_HEAP_PROFILER_EVENT_FILTER_H_ - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/trace_event/trace_event_filter.h" - -namespace base { -namespace trace_event { - -class TraceEvent; - -// This filter unconditionally accepts all events and pushes/pops them from the -// thread-local AllocationContextTracker instance as they are seen. -// This is used to cheaply construct the heap profiler pseudo stack without -// having to actually record all events. -class BASE_EXPORT HeapProfilerEventFilter : public TraceEventFilter { - public: - static const char kName[]; - - HeapProfilerEventFilter(); - ~HeapProfilerEventFilter() override; - - // TraceEventFilter implementation. - bool FilterTraceEvent(const TraceEvent& trace_event) const override; - void EndEvent(const char* category_name, - const char* event_name) const override; - - private: - DISALLOW_COPY_AND_ASSIGN(HeapProfilerEventFilter); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_EVENT_FILTER_H_
diff --git a/base/trace_event/heap_profiler_heap_dump_writer.cc b/base/trace_event/heap_profiler_heap_dump_writer.cc deleted file mode 100644 index 71c3d97..0000000 --- a/base/trace_event/heap_profiler_heap_dump_writer.cc +++ /dev/null
@@ -1,323 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/heap_profiler_heap_dump_writer.h" - -#include <stdint.h> - -#include <algorithm> -#include <iterator> -#include <tuple> -#include <utility> -#include <vector> - -#include "base/format_macros.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/heap_profiler_serialization_state.h" -#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" -#include "base/trace_event/heap_profiler_type_name_deduplicator.h" -#include "base/trace_event/trace_config.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" -#include "base/trace_event/trace_log.h" - -// Most of what the |HeapDumpWriter| does is aggregating detailed information -// about the heap and deciding what to dump. The Input to this process is a list -// of |AllocationContext|s and size pairs. -// -// The pairs are grouped into |Bucket|s. A bucket is a group of (context, size) -// pairs where the properties of the contexts share a prefix. (Type name is -// considered a list of length one here.) First all pairs are put into one -// bucket that represents the entire heap. Then this bucket is recursively -// broken down into smaller buckets. Each bucket keeps track of whether further -// breakdown is possible. - -namespace base { -namespace trace_event { -namespace internal { -namespace { - -// Denotes a property of |AllocationContext| to break down by. -enum class BreakDownMode { kByBacktrace, kByTypeName }; - -// A group of bytes for which the context shares a prefix. -struct Bucket { - Bucket() - : size(0), - count(0), - backtrace_cursor(0), - is_broken_down_by_type_name(false) {} - - std::vector<std::pair<const AllocationContext*, AllocationMetrics>> - metrics_by_context; - - // The sum of the sizes of |metrics_by_context|. - size_t size; - - // The sum of number of allocations of |metrics_by_context|. - size_t count; - - // The index of the stack frame that has not yet been broken down by. For all - // elements in this bucket, the stack frames 0 up to (but not including) the - // cursor, must be equal. - size_t backtrace_cursor; - - // When true, the type name for all elements in this bucket must be equal. - bool is_broken_down_by_type_name; -}; - -// Comparison operator to order buckets by their size. -bool operator<(const Bucket& lhs, const Bucket& rhs) { - return lhs.size < rhs.size; -} - -// Groups the allocations in the bucket by |break_by|. The buckets in the -// returned list will have |backtrace_cursor| advanced or -// |is_broken_down_by_type_name| set depending on the property to group by. -std::vector<Bucket> GetSubbuckets(const Bucket& bucket, - BreakDownMode break_by) { - std::unordered_map<const void*, Bucket> breakdown; - - if (break_by == BreakDownMode::kByBacktrace) { - for (const auto& context_and_metrics : bucket.metrics_by_context) { - const Backtrace& backtrace = context_and_metrics.first->backtrace; - const StackFrame* begin = std::begin(backtrace.frames); - const StackFrame* end = begin + backtrace.frame_count; - const StackFrame* cursor = begin + bucket.backtrace_cursor; - - DCHECK_LE(cursor, end); - - if (cursor != end) { - Bucket& subbucket = breakdown[cursor->value]; - subbucket.size += context_and_metrics.second.size; - subbucket.count += context_and_metrics.second.count; - subbucket.metrics_by_context.push_back(context_and_metrics); - subbucket.backtrace_cursor = bucket.backtrace_cursor + 1; - subbucket.is_broken_down_by_type_name = - bucket.is_broken_down_by_type_name; - DCHECK_GT(subbucket.size, 0u); - DCHECK_GT(subbucket.count, 0u); - } - } - } else if (break_by == BreakDownMode::kByTypeName) { - if (!bucket.is_broken_down_by_type_name) { - for (const auto& context_and_metrics : bucket.metrics_by_context) { - const AllocationContext* context = context_and_metrics.first; - Bucket& subbucket = breakdown[context->type_name]; - subbucket.size += context_and_metrics.second.size; - subbucket.count += context_and_metrics.second.count; - subbucket.metrics_by_context.push_back(context_and_metrics); - subbucket.backtrace_cursor = bucket.backtrace_cursor; - subbucket.is_broken_down_by_type_name = true; - DCHECK_GT(subbucket.size, 0u); - DCHECK_GT(subbucket.count, 0u); - } - } - } - - std::vector<Bucket> buckets; - buckets.reserve(breakdown.size()); - for (auto key_bucket : breakdown) - buckets.push_back(key_bucket.second); - - return buckets; -} - -// Breaks down the bucket by |break_by|. Returns only buckets that contribute -// more than |min_size_bytes| to the total size. The long tail is omitted. -std::vector<Bucket> BreakDownBy(const Bucket& bucket, - BreakDownMode break_by, - size_t min_size_bytes) { - std::vector<Bucket> buckets = GetSubbuckets(bucket, break_by); - - // Ensure that |buckets| is a max-heap (the data structure, not memory heap), - // so its front contains the largest bucket. Buckets should be iterated - // ordered by size, but sorting the vector is overkill because the long tail - // of small buckets will be discarded. By using a max-heap, the optimal case - // where all but the first bucket are discarded is O(n). The worst case where - // no bucket is discarded is doing a heap sort, which is O(n log n). - std::make_heap(buckets.begin(), buckets.end()); - - // Keep including buckets until adding one would increase the number of - // bytes accounted for by |min_size_bytes|. The large buckets end up in - // [it, end()), [begin(), it) is the part that contains the max-heap - // of small buckets. - std::vector<Bucket>::iterator it; - for (it = buckets.end(); it != buckets.begin(); --it) { - if (buckets.front().size < min_size_bytes) - break; - - // Put the largest bucket in [begin, it) at |it - 1| and max-heapify - // [begin, it - 1). This puts the next largest bucket at |buckets.front()|. - std::pop_heap(buckets.begin(), it); - } - - // At this point, |buckets| looks like this (numbers are bucket sizes): - // - // <-- max-heap of small buckets ---> - // <-- large buckets by ascending size --> - // [ 19 | 11 | 13 | 7 | 2 | 5 | ... | 83 | 89 | 97 ] - // ^ ^ ^ - // | | | - // begin() it end() - - // Discard the long tail of buckets that contribute less than a percent. - buckets.erase(buckets.begin(), it); - - return buckets; -} - -} // namespace - -bool operator<(Entry lhs, Entry rhs) { - // There is no need to compare |size|. If the backtrace and type name are - // equal then the sizes must be equal as well. - return std::tie(lhs.stack_frame_id, lhs.type_id) < - std::tie(rhs.stack_frame_id, rhs.type_id); -} - -HeapDumpWriter::HeapDumpWriter(StackFrameDeduplicator* stack_frame_deduplicator, - TypeNameDeduplicator* type_name_deduplicator, - uint32_t breakdown_threshold_bytes) - : stack_frame_deduplicator_(stack_frame_deduplicator), - type_name_deduplicator_(type_name_deduplicator), - breakdown_threshold_bytes_(breakdown_threshold_bytes) {} - -HeapDumpWriter::~HeapDumpWriter() = default; - -bool HeapDumpWriter::AddEntryForBucket(const Bucket& bucket) { - // The contexts in the bucket are all different, but the [begin, cursor) range - // is equal for all contexts in the bucket, and the type names are the same if - // |is_broken_down_by_type_name| is set. - DCHECK(!bucket.metrics_by_context.empty()); - - const AllocationContext* context = bucket.metrics_by_context.front().first; - - const StackFrame* backtrace_begin = std::begin(context->backtrace.frames); - const StackFrame* backtrace_end = backtrace_begin + bucket.backtrace_cursor; - DCHECK_LE(bucket.backtrace_cursor, arraysize(context->backtrace.frames)); - - Entry entry; - entry.stack_frame_id = - stack_frame_deduplicator_->Insert(backtrace_begin, backtrace_end); - - // Deduplicate the type name, or use ID -1 if type name is not set. - entry.type_id = bucket.is_broken_down_by_type_name - ? type_name_deduplicator_->Insert(context->type_name) - : -1; - - entry.size = bucket.size; - entry.count = bucket.count; - - auto position_and_inserted = entries_.insert(entry); - return position_and_inserted.second; -} - -void HeapDumpWriter::BreakDown(const Bucket& bucket) { - auto by_backtrace = BreakDownBy(bucket, BreakDownMode::kByBacktrace, - breakdown_threshold_bytes_); - auto by_type_name = BreakDownBy(bucket, BreakDownMode::kByTypeName, - breakdown_threshold_bytes_); - - // Insert entries for the buckets. If a bucket was not present before, it has - // not been broken down before, so recursively continue breaking down in that - // case. There might be multiple routes to the same entry (first break down - // by type name, then by backtrace, or first by backtrace and then by type), - // so a set is used to avoid dumping and breaking down entries more than once. - - for (const Bucket& subbucket : by_backtrace) - if (AddEntryForBucket(subbucket)) - BreakDown(subbucket); - - for (const Bucket& subbucket : by_type_name) - if (AddEntryForBucket(subbucket)) - BreakDown(subbucket); -} - -const std::set<Entry>& HeapDumpWriter::Summarize( - const std::unordered_map<AllocationContext, AllocationMetrics>& - metrics_by_context) { - // Start with one bucket that represents the entire heap. Iterate by - // reference, because the allocation contexts are going to point to allocation - // contexts stored in |metrics_by_context|. - Bucket root_bucket; - for (const auto& context_and_metrics : metrics_by_context) { - DCHECK_GT(context_and_metrics.second.size, 0u); - DCHECK_GT(context_and_metrics.second.count, 0u); - const AllocationContext* context = &context_and_metrics.first; - root_bucket.metrics_by_context.push_back( - std::make_pair(context, context_and_metrics.second)); - root_bucket.size += context_and_metrics.second.size; - root_bucket.count += context_and_metrics.second.count; - } - - AddEntryForBucket(root_bucket); - - // Recursively break down the heap and fill |entries_| with entries to dump. - BreakDown(root_bucket); - - return entries_; -} - -std::unique_ptr<TracedValue> Serialize(const std::set<Entry>& entries) { - std::string buffer; - std::unique_ptr<TracedValue> traced_value(new TracedValue); - - traced_value->BeginArray("entries"); - - for (const Entry& entry : entries) { - traced_value->BeginDictionary(); - - // Format size as hexadecimal string into |buffer|. - SStringPrintf(&buffer, "%" PRIx64, static_cast<uint64_t>(entry.size)); - traced_value->SetString("size", buffer); - - SStringPrintf(&buffer, "%" PRIx64, static_cast<uint64_t>(entry.count)); - traced_value->SetString("count", buffer); - - if (entry.stack_frame_id == -1) { - // An empty backtrace (which will have ID -1) is represented by the empty - // string, because there is no leaf frame to reference in |stackFrames|. - traced_value->SetString("bt", ""); - } else { - // Format index of the leaf frame as a string, because |stackFrames| is a - // dictionary, not an array. - SStringPrintf(&buffer, "%i", entry.stack_frame_id); - traced_value->SetString("bt", buffer); - } - - // Type ID -1 (cumulative size for all types) is represented by the absence - // of the "type" key in the dictionary. - if (entry.type_id != -1) { - // Format the type ID as a string. - SStringPrintf(&buffer, "%i", entry.type_id); - traced_value->SetString("type", buffer); - } - - traced_value->EndDictionary(); - } - - traced_value->EndArray(); // "entries" - return traced_value; -} - -} // namespace internal - -std::unique_ptr<TracedValue> ExportHeapDump( - const std::unordered_map<AllocationContext, AllocationMetrics>& - metrics_by_context, - const HeapProfilerSerializationState& heap_profiler_serialization_state) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), "ExportHeapDump"); - internal::HeapDumpWriter writer( - heap_profiler_serialization_state.stack_frame_deduplicator(), - heap_profiler_serialization_state.type_name_deduplicator(), - heap_profiler_serialization_state - .heap_profiler_breakdown_threshold_bytes()); - return Serialize(writer.Summarize(metrics_by_context)); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/heap_profiler_heap_dump_writer.h b/base/trace_event/heap_profiler_heap_dump_writer.h deleted file mode 100644 index 3366c28..0000000 --- a/base/trace_event/heap_profiler_heap_dump_writer.h +++ /dev/null
@@ -1,115 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_HEAP_DUMP_WRITER_H_ -#define BASE_TRACE_EVENT_HEAP_PROFILER_HEAP_DUMP_WRITER_H_ - -#include <stddef.h> - -#include <memory> -#include <set> -#include <unordered_map> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/trace_event/heap_profiler_allocation_context.h" - -namespace base { -namespace trace_event { - -class HeapProfilerSerializationState; -class StackFrameDeduplicator; -class TracedValue; -class TypeNameDeduplicator; - -// Aggregates |metrics_by_context|, recursively breaks down the heap, and -// returns a traced value with an "entries" array that can be dumped in the -// trace log, following the format described in https://goo.gl/KY7zVE. The -// number of entries is kept reasonable because long tails are not included. -BASE_EXPORT std::unique_ptr<TracedValue> ExportHeapDump( - const std::unordered_map<AllocationContext, AllocationMetrics>& - metrics_by_context, - const HeapProfilerSerializationState& heap_profiler_serialization_state); - -namespace internal { - -namespace { -struct Bucket; -} - -// An entry in the "entries" array as described in https://goo.gl/KY7zVE. -struct BASE_EXPORT Entry { - size_t size; - size_t count; - - // References a backtrace in the stack frame deduplicator. -1 means empty - // backtrace (the root of the tree). - int stack_frame_id; - - // References a type name in the type name deduplicator. -1 indicates that - // the size is the cumulative size for all types (the root of the tree). - int type_id; -}; - -// Comparison operator to enable putting |Entry| in a |std::set|. -BASE_EXPORT bool operator<(Entry lhs, Entry rhs); - -// Serializes entries to an "entries" array in a traced value. -BASE_EXPORT std::unique_ptr<TracedValue> Serialize(const std::set<Entry>& dump); - -// Helper class to dump a snapshot of an |AllocationRegister| or other heap -// bookkeeping structure into a |TracedValue|. This class is intended to be -// used as a one-shot local instance on the stack. -class BASE_EXPORT HeapDumpWriter { - public: - // The |stack_frame_deduplicator| and |type_name_deduplicator| are not owned. - // The heap dump writer assumes exclusive access to them during the lifetime - // of the dump writer. The heap dumps are broken down for allocations bigger - // than |breakdown_threshold_bytes|. - HeapDumpWriter(StackFrameDeduplicator* stack_frame_deduplicator, - TypeNameDeduplicator* type_name_deduplicator, - uint32_t breakdown_threshold_bytes); - - ~HeapDumpWriter(); - - // Aggregates allocations to compute the total size of the heap, then breaks - // down the heap recursively. This produces the values that should be dumped - // in the "entries" array. The number of entries is kept reasonable because - // long tails are not included. Use |Serialize| to convert to a traced value. - const std::set<Entry>& Summarize( - const std::unordered_map<AllocationContext, AllocationMetrics>& - metrics_by_context); - - private: - // Inserts an |Entry| for |Bucket| into |entries_|. Returns false if the - // entry was present before, true if it was not. - bool AddEntryForBucket(const Bucket& bucket); - - // Recursively breaks down a bucket into smaller buckets and adds entries for - // the buckets worth dumping to |entries_|. - void BreakDown(const Bucket& bucket); - - // The collection of entries that is filled by |Summarize|. - std::set<Entry> entries_; - - // Helper for generating the |stackFrames| dictionary. Not owned, must outlive - // this heap dump writer instance. - StackFrameDeduplicator* const stack_frame_deduplicator_; - - // Helper for converting type names to IDs. Not owned, must outlive this heap - // dump writer instance. - TypeNameDeduplicator* const type_name_deduplicator_; - - // Minimum size of an allocation for which an allocation bucket will be - // broken down with children. - uint32_t breakdown_threshold_bytes_; - - DISALLOW_COPY_AND_ASSIGN(HeapDumpWriter); -}; - -} // namespace internal -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_HEAP_DUMP_WRITER_H_
diff --git a/base/trace_event/heap_profiler_serialization_state.cc b/base/trace_event/heap_profiler_serialization_state.cc deleted file mode 100644 index b1866e7..0000000 --- a/base/trace_event/heap_profiler_serialization_state.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/heap_profiler_serialization_state.h" - -namespace base { -namespace trace_event { - -HeapProfilerSerializationState::HeapProfilerSerializationState() - : heap_profiler_breakdown_threshold_bytes_(0) {} -HeapProfilerSerializationState::~HeapProfilerSerializationState() = default; - -void HeapProfilerSerializationState::SetStackFrameDeduplicator( - std::unique_ptr<StackFrameDeduplicator> stack_frame_deduplicator) { - DCHECK(!stack_frame_deduplicator_); - stack_frame_deduplicator_ = std::move(stack_frame_deduplicator); -} - -void HeapProfilerSerializationState::SetTypeNameDeduplicator( - std::unique_ptr<TypeNameDeduplicator> type_name_deduplicator) { - DCHECK(!type_name_deduplicator_); - type_name_deduplicator_ = std::move(type_name_deduplicator); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/heap_profiler_serialization_state.h b/base/trace_event/heap_profiler_serialization_state.h deleted file mode 100644 index 53c5687..0000000 --- a/base/trace_event/heap_profiler_serialization_state.h +++ /dev/null
@@ -1,80 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_SERIALIZATION_STATE_H_ -#define BASE_TRACE_EVENT_HEAP_PROFILER_SERIALIZATION_STATE_H_ - -#include <memory> -#include <set> - -#include "base/base_export.h" -#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" -#include "base/trace_event/heap_profiler_type_name_deduplicator.h" -#include "base/trace_event/memory_dump_request_args.h" - -namespace base { -namespace trace_event { - -// Container for state variables that should be shared across all the memory -// dumps in a tracing session. -class BASE_EXPORT HeapProfilerSerializationState - : public RefCountedThreadSafe<HeapProfilerSerializationState> { - public: - HeapProfilerSerializationState(); - - // Returns the stack frame deduplicator that should be used by memory dump - // providers when doing a heap dump. - StackFrameDeduplicator* stack_frame_deduplicator() const { - return stack_frame_deduplicator_.get(); - } - - void SetStackFrameDeduplicator( - std::unique_ptr<StackFrameDeduplicator> stack_frame_deduplicator); - - // Returns the type name deduplicator that should be used by memory dump - // providers when doing a heap dump. - TypeNameDeduplicator* type_name_deduplicator() const { - return type_name_deduplicator_.get(); - } - - void SetTypeNameDeduplicator( - std::unique_ptr<TypeNameDeduplicator> type_name_deduplicator); - - void SetAllowedDumpModes( - std::set<MemoryDumpLevelOfDetail> allowed_dump_modes); - - bool IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) const; - - void set_heap_profiler_breakdown_threshold_bytes(uint32_t value) { - heap_profiler_breakdown_threshold_bytes_ = value; - } - - uint32_t heap_profiler_breakdown_threshold_bytes() const { - return heap_profiler_breakdown_threshold_bytes_; - } - - bool is_initialized() const { - return stack_frame_deduplicator_ && type_name_deduplicator_ && - heap_profiler_breakdown_threshold_bytes_; - } - - private: - friend class RefCountedThreadSafe<HeapProfilerSerializationState>; - ~HeapProfilerSerializationState(); - - // Deduplicates backtraces in heap dumps so they can be written once when the - // trace is finalized. - std::unique_ptr<StackFrameDeduplicator> stack_frame_deduplicator_; - - // Deduplicates type names in heap dumps so they can be written once when the - // trace is finalized. - std::unique_ptr<TypeNameDeduplicator> type_name_deduplicator_; - - uint32_t heap_profiler_breakdown_threshold_bytes_; -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_SERIALIZATION_STATE_H
diff --git a/base/trace_event/heap_profiler_stack_frame_deduplicator.cc b/base/trace_event/heap_profiler_stack_frame_deduplicator.cc deleted file mode 100644 index c05cd0a..0000000 --- a/base/trace_event/heap_profiler_stack_frame_deduplicator.cc +++ /dev/null
@@ -1,195 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" - -#include <inttypes.h> -#include <stddef.h> - -#include <algorithm> -#include <string> -#include <utility> - -#include "base/hash.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/memory_usage_estimator.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" -#include "base/trace_event/trace_event_memory_overhead.h" - -namespace base { -namespace trace_event { - -namespace { - -// Dumb hash function that nevertheless works surprisingly well and -// produces ~0 collisions on real backtraces. -size_t HashBacktrace(const StackFrame* begin, const StackFrame* end) { - size_t hash = 0; - for (; begin != end; begin++) { - hash += reinterpret_cast<uintptr_t>(begin->value); - } - return hash; -} - -} // namespace - -StackFrameDeduplicator::FrameNode::FrameNode(StackFrame frame, - int parent_frame_index) - : frame(frame), parent_frame_index(parent_frame_index) {} -StackFrameDeduplicator::FrameNode::FrameNode(const FrameNode& other) = default; -StackFrameDeduplicator::FrameNode::~FrameNode() = default; - -size_t StackFrameDeduplicator::FrameNode::EstimateMemoryUsage() const { - return base::trace_event::EstimateMemoryUsage(children); -} - -StackFrameDeduplicator::StackFrameDeduplicator() = default; -StackFrameDeduplicator::~StackFrameDeduplicator() = default; - -bool StackFrameDeduplicator::Match(int frame_index, - const StackFrame* begin_frame, - const StackFrame* end_frame) const { - // |frame_index| identifies the bottom frame, i.e. we need to walk - // backtrace backwards. - const StackFrame* current_frame = end_frame - 1; - for (; current_frame >= begin_frame; --current_frame) { - const FrameNode& node = frames_[frame_index]; - if (node.frame != *current_frame) { - break; - } - - frame_index = node.parent_frame_index; - if (frame_index == FrameNode::kInvalidFrameIndex) { - if (current_frame == begin_frame) { - // We're at the top node and we matched all backtrace frames, - // i.e. we successfully matched the backtrace. - return true; - } - break; - } - } - - return false; -} - -int StackFrameDeduplicator::Insert(const StackFrame* begin_frame, - const StackFrame* end_frame) { - if (begin_frame == end_frame) { - return FrameNode::kInvalidFrameIndex; - } - - size_t backtrace_hash = HashBacktrace(begin_frame, end_frame); - - // Check if we know about this backtrace. - auto backtrace_it = backtrace_lookup_table_.find(backtrace_hash); - if (backtrace_it != backtrace_lookup_table_.end()) { - int backtrace_index = backtrace_it->second; - if (Match(backtrace_index, begin_frame, end_frame)) { - return backtrace_index; - } - } - - int frame_index = FrameNode::kInvalidFrameIndex; - base::flat_map<StackFrame, int>* nodes = &roots_; - - // Loop through the frames, early out when a frame is null. - for (const StackFrame* it = begin_frame; it != end_frame; it++) { - StackFrame frame = *it; - - auto node = nodes->find(frame); - if (node == nodes->end()) { - // There is no tree node for this frame yet, create it. The parent node - // is the node associated with the previous frame. - FrameNode frame_node(frame, frame_index); - - // The new frame node will be appended, so its index is the current size - // of the vector. - frame_index = static_cast<int>(frames_.size()); - - // Add the node to the trie so it will be found next time. - nodes->insert(std::make_pair(frame, frame_index)); - - // Append the node after modifying |nodes|, because the |frames_| vector - // might need to resize, and this invalidates the |nodes| pointer. - frames_.push_back(frame_node); - } else { - // A tree node for this frame exists. Look for the next one. - frame_index = node->second; - } - - nodes = &frames_[frame_index].children; - } - - // Remember the backtrace. - backtrace_lookup_table_[backtrace_hash] = frame_index; - - return frame_index; -} - -void StackFrameDeduplicator::AppendAsTraceFormat(std::string* out) const { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), - "StackFrameDeduplicator::AppendAsTraceFormat"); - out->append("{"); // Begin the |stackFrames| dictionary. - - int i = 0; - auto frame_node = begin(); - auto it_end = end(); - std::string stringify_buffer; - - while (frame_node != it_end) { - // The |stackFrames| format is a dictionary, not an array, so the - // keys are stringified indices. Write the index manually, then use - // |TracedValue| to format the object. This is to avoid building the - // entire dictionary as a |TracedValue| in memory. - SStringPrintf(&stringify_buffer, "\"%d\":", i); - out->append(stringify_buffer); - - std::unique_ptr<TracedValue> frame_node_value(new TracedValue); - const StackFrame& frame = frame_node->frame; - switch (frame.type) { - case StackFrame::Type::TRACE_EVENT_NAME: - frame_node_value->SetString("name", - static_cast<const char*>(frame.value)); - break; - case StackFrame::Type::THREAD_NAME: - SStringPrintf(&stringify_buffer, - "[Thread: %s]", - static_cast<const char*>(frame.value)); - frame_node_value->SetString("name", stringify_buffer); - break; - case StackFrame::Type::PROGRAM_COUNTER: - SStringPrintf(&stringify_buffer, - "pc:%" PRIxPTR, - reinterpret_cast<uintptr_t>(frame.value)); - frame_node_value->SetString("name", stringify_buffer); - break; - } - if (frame_node->parent_frame_index != FrameNode::kInvalidFrameIndex) { - SStringPrintf(&stringify_buffer, "%d", frame_node->parent_frame_index); - frame_node_value->SetString("parent", stringify_buffer); - } - frame_node_value->AppendAsTraceFormat(out); - - i++; - frame_node++; - - if (frame_node != it_end) - out->append(","); - } - - out->append("}"); // End the |stackFrames| dictionary. -} - -void StackFrameDeduplicator::EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) { - size_t memory_usage = EstimateMemoryUsage(frames_) + - EstimateMemoryUsage(roots_) + - EstimateMemoryUsage(backtrace_lookup_table_); - overhead->Add(TraceEventMemoryOverhead::kHeapProfilerStackFrameDeduplicator, - sizeof(StackFrameDeduplicator) + memory_usage); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/heap_profiler_stack_frame_deduplicator.h b/base/trace_event/heap_profiler_stack_frame_deduplicator.h deleted file mode 100644 index ac8d895..0000000 --- a/base/trace_event/heap_profiler_stack_frame_deduplicator.h +++ /dev/null
@@ -1,94 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_STACK_FRAME_DEDUPLICATOR_H_ -#define BASE_TRACE_EVENT_HEAP_PROFILER_STACK_FRAME_DEDUPLICATOR_H_ - -#include <string> -#include <unordered_map> - -#include "base/base_export.h" -#include "base/containers/circular_deque.h" -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "base/trace_event/heap_profiler_allocation_context.h" -#include "base/trace_event/trace_event_impl.h" - -namespace base { -namespace trace_event { - -class TraceEventMemoryOverhead; - -// A data structure that allows grouping a set of backtraces in a space- -// efficient manner by creating a call tree and writing it as a set of (node, -// parent) pairs. The tree nodes reference both parent and children. The parent -// is referenced by index into |frames_|. The children are referenced via a map -// of |StackFrame|s to index into |frames_|. So there is a trie for bottum-up -// lookup of a backtrace for deduplication, and a tree for compact storage in -// the trace log. -class BASE_EXPORT StackFrameDeduplicator : public ConvertableToTraceFormat { - public: - // A node in the call tree. - struct FrameNode { - FrameNode(StackFrame frame, int parent_frame_index); - FrameNode(const FrameNode& other); - ~FrameNode(); - - size_t EstimateMemoryUsage() const; - - StackFrame frame; - - // The index of the parent stack frame in |frames_|, or kInvalidFrameIndex - // if there is no parent frame (when it is at the bottom of the call stack). - int parent_frame_index; - constexpr static int kInvalidFrameIndex = -1; - - // Indices into |frames_| of frames called from the current frame. - base::flat_map<StackFrame, int> children; - }; - - using ConstIterator = base::circular_deque<FrameNode>::const_iterator; - - StackFrameDeduplicator(); - ~StackFrameDeduplicator() override; - - // Inserts a backtrace where |beginFrame| is a pointer to the bottom frame - // (e.g. main) and |endFrame| is a pointer past the top frame (most recently - // called function), and returns the index of its leaf node in |frames_|. - // Returns -1 if the backtrace is empty. - int Insert(const StackFrame* beginFrame, const StackFrame* endFrame); - - // Iterators over the frame nodes in the call tree. - ConstIterator begin() const { return frames_.begin(); } - ConstIterator end() const { return frames_.end(); } - - // Writes the |stackFrames| dictionary as defined in https://goo.gl/GerkV8 to - // the trace log. - void AppendAsTraceFormat(std::string* out) const override; - - // Estimates memory overhead including |sizeof(StackFrameDeduplicator)|. - void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override; - - private: - // Checks that existing backtrace identified by |frame_index| equals - // to the one identified by |begin_frame|, |end_frame|. - bool Match(int frame_index, - const StackFrame* begin_frame, - const StackFrame* end_frame) const; - - base::flat_map<StackFrame, int> roots_; - base::circular_deque<FrameNode> frames_; - - // {backtrace_hash -> frame_index} map for finding backtraces that are - // already added. Backtraces themselves are not stored in the map, instead - // Match() is used on the found frame_index to detect collisions. - std::unordered_map<size_t, int> backtrace_lookup_table_; - - DISALLOW_COPY_AND_ASSIGN(StackFrameDeduplicator); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_STACK_FRAME_DEDUPLICATOR_H_
diff --git a/base/trace_event/heap_profiler_type_name_deduplicator.cc b/base/trace_event/heap_profiler_type_name_deduplicator.cc deleted file mode 100644 index 360f239..0000000 --- a/base/trace_event/heap_profiler_type_name_deduplicator.cc +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/heap_profiler_type_name_deduplicator.h" - -#include <stddef.h> -#include <stdlib.h> -#include <string> -#include <utility> - -#include "base/json/string_escape.h" -#include "base/strings/string_split.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/memory_usage_estimator.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_memory_overhead.h" - -namespace base { -namespace trace_event { - -TypeNameDeduplicator::TypeNameDeduplicator() { - // A null pointer has type ID 0 ("unknown type"); - type_ids_.insert(std::make_pair(nullptr, 0)); -} - -TypeNameDeduplicator::~TypeNameDeduplicator() = default; - -int TypeNameDeduplicator::Insert(const char* type_name) { - auto result = type_ids_.insert(std::make_pair(type_name, 0)); - auto& elem = result.first; - bool did_not_exist_before = result.second; - - if (did_not_exist_before) { - // The type IDs are assigned sequentially and they are zero-based, so - // |size() - 1| is the ID of the new element. - elem->second = static_cast<int>(type_ids_.size() - 1); - } - - return elem->second; -} - -void TypeNameDeduplicator::AppendAsTraceFormat(std::string* out) const { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), - "TypeNameDeduplicator::AppendAsTraceFormat"); - out->append("{"); // Begin the type names dictionary. - - auto it = type_ids_.begin(); - std::string buffer; - - // Write the first entry manually; the null pointer must not be dereferenced. - // (The first entry is the null pointer because a |std::map| is ordered.) - it++; - out->append("\"0\":\"[unknown]\""); - - for (; it != type_ids_.end(); it++) { - // Type IDs in the trace are strings, write them as stringified keys of - // a dictionary. - SStringPrintf(&buffer, ",\"%d\":", it->second); - - // TODO(ssid): crbug.com/594803 the type name is misused for file name in - // some cases. - StringPiece type_info = it->first; - - // |EscapeJSONString| appends, it does not overwrite |buffer|. - bool put_in_quotes = true; - EscapeJSONString(type_info, put_in_quotes, &buffer); - out->append(buffer); - } - - out->append("}"); // End the type names dictionary. -} - -void TypeNameDeduplicator::EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) { - size_t memory_usage = EstimateMemoryUsage(type_ids_); - overhead->Add(TraceEventMemoryOverhead::kHeapProfilerTypeNameDeduplicator, - sizeof(TypeNameDeduplicator) + memory_usage); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/heap_profiler_type_name_deduplicator.h b/base/trace_event/heap_profiler_type_name_deduplicator.h deleted file mode 100644 index 2d26c73..0000000 --- a/base/trace_event/heap_profiler_type_name_deduplicator.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_TYPE_NAME_DEDUPLICATOR_H_ -#define BASE_TRACE_EVENT_HEAP_PROFILER_TYPE_NAME_DEDUPLICATOR_H_ - -#include <map> -#include <string> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/trace_event/trace_event_impl.h" - -namespace base { -namespace trace_event { - -class TraceEventMemoryOverhead; - -// Data structure that assigns a unique numeric ID to |const char*|s. -class BASE_EXPORT TypeNameDeduplicator : public ConvertableToTraceFormat { - public: - TypeNameDeduplicator(); - ~TypeNameDeduplicator() override; - - // Inserts a type name and returns its ID. - int Insert(const char* type_name); - - // Writes the type ID -> type name mapping to the trace log. - void AppendAsTraceFormat(std::string* out) const override; - - // Estimates memory overhead including |sizeof(TypeNameDeduplicator)|. - void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override; - - private: - // Map from type name to type ID. - std::map<const char*, int> type_ids_; - - DISALLOW_COPY_AND_ASSIGN(TypeNameDeduplicator); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_HEAP_PROFILER_TYPE_NAME_DEDUPLICATOR_H_
diff --git a/base/trace_event/java_heap_dump_provider_android.cc b/base/trace_event/java_heap_dump_provider_android.cc deleted file mode 100644 index 684f730..0000000 --- a/base/trace_event/java_heap_dump_provider_android.cc +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/java_heap_dump_provider_android.h" - -#include "base/android/java_runtime.h" -#include "base/trace_event/process_memory_dump.h" - -namespace base { -namespace trace_event { - -// static -JavaHeapDumpProvider* JavaHeapDumpProvider::GetInstance() { - return Singleton<JavaHeapDumpProvider, - LeakySingletonTraits<JavaHeapDumpProvider>>::get(); -} - -JavaHeapDumpProvider::JavaHeapDumpProvider() { -} - -JavaHeapDumpProvider::~JavaHeapDumpProvider() { -} - -// Called at trace dump point time. Creates a snapshot with the memory counters -// for the current process. -bool JavaHeapDumpProvider::OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) { - // These numbers come from java.lang.Runtime stats. - long total_heap_size = 0; - long free_heap_size = 0; - android::JavaRuntime::GetMemoryUsage(&total_heap_size, &free_heap_size); - - MemoryAllocatorDump* outer_dump = pmd->CreateAllocatorDump("java_heap"); - outer_dump->AddScalar(MemoryAllocatorDump::kNameSize, - MemoryAllocatorDump::kUnitsBytes, total_heap_size); - - MemoryAllocatorDump* inner_dump = - pmd->CreateAllocatorDump("java_heap/allocated_objects"); - inner_dump->AddScalar(MemoryAllocatorDump::kNameSize, - MemoryAllocatorDump::kUnitsBytes, - total_heap_size - free_heap_size); - return true; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/java_heap_dump_provider_android.h b/base/trace_event/java_heap_dump_provider_android.h deleted file mode 100644 index b9f2333..0000000 --- a/base/trace_event/java_heap_dump_provider_android.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_ -#define BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_ - -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "base/trace_event/memory_dump_provider.h" - -namespace base { -namespace trace_event { - -// Dump provider which collects process-wide memory stats. -class BASE_EXPORT JavaHeapDumpProvider : public MemoryDumpProvider { - public: - static JavaHeapDumpProvider* GetInstance(); - - // MemoryDumpProvider implementation. - bool OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) override; - - private: - friend struct DefaultSingletonTraits<JavaHeapDumpProvider>; - - JavaHeapDumpProvider(); - ~JavaHeapDumpProvider() override; - - DISALLOW_COPY_AND_ASSIGN(JavaHeapDumpProvider); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
diff --git a/base/trace_event/malloc_dump_provider.cc b/base/trace_event/malloc_dump_provider.cc deleted file mode 100644 index 04a4dd5..0000000 --- a/base/trace_event/malloc_dump_provider.cc +++ /dev/null
@@ -1,188 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/malloc_dump_provider.h" - -#include <stddef.h> - -#include <unordered_map> - -#include "base/allocator/allocator_extension.h" -#include "base/debug/profiler.h" -#include "base/trace_event/process_memory_dump.h" -#include "base/trace_event/trace_event_argument.h" -#include "build_config.h" - -#if defined(OS_MACOSX) -#include <malloc/malloc.h> -#else -#include <malloc.h> -#endif -#if defined(OS_WIN) -#include <windows.h> -#endif - -namespace base { -namespace trace_event { - -namespace { -#if defined(OS_WIN) -// A structure containing some information about a given heap. -struct WinHeapInfo { - size_t committed_size; - size_t uncommitted_size; - size_t allocated_size; - size_t block_count; -}; - -// NOTE: crbug.com/665516 -// Unfortunately, there is no safe way to collect information from secondary -// heaps due to limitations and racy nature of this piece of WinAPI. -void WinHeapMemoryDumpImpl(WinHeapInfo* crt_heap_info) { - // Iterate through whichever heap our CRT is using. - HANDLE crt_heap = reinterpret_cast<HANDLE>(_get_heap_handle()); - ::HeapLock(crt_heap); - PROCESS_HEAP_ENTRY heap_entry; - heap_entry.lpData = nullptr; - // Walk over all the entries in the main heap. - while (::HeapWalk(crt_heap, &heap_entry) != FALSE) { - if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) { - crt_heap_info->allocated_size += heap_entry.cbData; - crt_heap_info->block_count++; - } else if ((heap_entry.wFlags & PROCESS_HEAP_REGION) != 0) { - crt_heap_info->committed_size += heap_entry.Region.dwCommittedSize; - crt_heap_info->uncommitted_size += heap_entry.Region.dwUnCommittedSize; - } - } - CHECK(::HeapUnlock(crt_heap) == TRUE); -} -#endif // defined(OS_WIN) -} // namespace - -// static -const char MallocDumpProvider::kAllocatedObjects[] = "malloc/allocated_objects"; - -// static -MallocDumpProvider* MallocDumpProvider::GetInstance() { - return Singleton<MallocDumpProvider, - LeakySingletonTraits<MallocDumpProvider>>::get(); -} - -MallocDumpProvider::MallocDumpProvider() = default; -MallocDumpProvider::~MallocDumpProvider() = default; - -// Called at trace dump point time. Creates a snapshot the memory counters for -// the current process. -bool MallocDumpProvider::OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) { - { - base::AutoLock auto_lock(emit_metrics_on_memory_dump_lock_); - if (!emit_metrics_on_memory_dump_) - return true; - } - - size_t total_virtual_size = 0; - size_t resident_size = 0; - size_t allocated_objects_size = 0; - size_t allocated_objects_count = 0; -#if defined(USE_TCMALLOC) - bool res = - allocator::GetNumericProperty("generic.heap_size", &total_virtual_size); - DCHECK(res); - res = allocator::GetNumericProperty("generic.total_physical_bytes", - &resident_size); - DCHECK(res); - res = allocator::GetNumericProperty("generic.current_allocated_bytes", - &allocated_objects_size); - DCHECK(res); -#elif defined(OS_MACOSX) || defined(OS_IOS) - malloc_statistics_t stats = {0}; - malloc_zone_statistics(nullptr, &stats); - total_virtual_size = stats.size_allocated; - allocated_objects_size = stats.size_in_use; - - // Resident size is approximated pretty well by stats.max_size_in_use. - // However, on macOS, freed blocks are both resident and reusable, which is - // semantically equivalent to deallocated. The implementation of libmalloc - // will also only hold a fixed number of freed regions before actually - // starting to deallocate them, so stats.max_size_in_use is also not - // representative of the peak size. As a result, stats.max_size_in_use is - // typically somewhere between actually resident [non-reusable] pages, and - // peak size. This is not very useful, so we just use stats.size_in_use for - // resident_size, even though it's an underestimate and fails to account for - // fragmentation. See - // https://bugs.chromium.org/p/chromium/issues/detail?id=695263#c1. - resident_size = stats.size_in_use; -#elif defined(OS_WIN) - // This is too expensive on Windows, crbug.com/780735. - if (args.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { - WinHeapInfo main_heap_info = {}; - WinHeapMemoryDumpImpl(&main_heap_info); - total_virtual_size = - main_heap_info.committed_size + main_heap_info.uncommitted_size; - // Resident size is approximated with committed heap size. Note that it is - // possible to do this with better accuracy on windows by intersecting the - // working set with the virtual memory ranges occuipied by the heap. It's - // not clear that this is worth it, as it's fairly expensive to do. - resident_size = main_heap_info.committed_size; - allocated_objects_size = main_heap_info.allocated_size; - allocated_objects_count = main_heap_info.block_count; - } -#elif defined(OS_FUCHSIA) -// TODO(fuchsia): Port, see https://crbug.com/706592. -#else - struct mallinfo info = mallinfo(); - DCHECK_GE(info.arena + info.hblkhd, info.uordblks); - - // In case of Android's jemalloc |arena| is 0 and the outer pages size is - // reported by |hblkhd|. In case of dlmalloc the total is given by - // |arena| + |hblkhd|. For more details see link: http://goo.gl/fMR8lF. - total_virtual_size = info.arena + info.hblkhd; - resident_size = info.uordblks; - - // Total allocated space is given by |uordblks|. - allocated_objects_size = info.uordblks; -#endif - - MemoryAllocatorDump* outer_dump = pmd->CreateAllocatorDump("malloc"); - outer_dump->AddScalar("virtual_size", MemoryAllocatorDump::kUnitsBytes, - total_virtual_size); - outer_dump->AddScalar(MemoryAllocatorDump::kNameSize, - MemoryAllocatorDump::kUnitsBytes, resident_size); - - MemoryAllocatorDump* inner_dump = pmd->CreateAllocatorDump(kAllocatedObjects); - inner_dump->AddScalar(MemoryAllocatorDump::kNameSize, - MemoryAllocatorDump::kUnitsBytes, - allocated_objects_size); - if (allocated_objects_count != 0) { - inner_dump->AddScalar(MemoryAllocatorDump::kNameObjectCount, - MemoryAllocatorDump::kUnitsObjects, - allocated_objects_count); - } - - if (resident_size > allocated_objects_size) { - // Explicitly specify why is extra memory resident. In tcmalloc it accounts - // for free lists and caches. In mac and ios it accounts for the - // fragmentation and metadata. - MemoryAllocatorDump* other_dump = - pmd->CreateAllocatorDump("malloc/metadata_fragmentation_caches"); - other_dump->AddScalar(MemoryAllocatorDump::kNameSize, - MemoryAllocatorDump::kUnitsBytes, - resident_size - allocated_objects_size); - } - return true; -} - -void MallocDumpProvider::EnableMetrics() { - base::AutoLock auto_lock(emit_metrics_on_memory_dump_lock_); - emit_metrics_on_memory_dump_ = true; -} - -void MallocDumpProvider::DisableMetrics() { - base::AutoLock auto_lock(emit_metrics_on_memory_dump_lock_); - emit_metrics_on_memory_dump_ = false; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/malloc_dump_provider.h b/base/trace_event/malloc_dump_provider.h deleted file mode 100644 index 726c382..0000000 --- a/base/trace_event/malloc_dump_provider.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_ -#define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_ - -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" -#include "base/trace_event/memory_dump_provider.h" -#include "build_config.h" - -#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_WIN) || \ - (defined(OS_MACOSX) && !defined(OS_IOS)) -#define MALLOC_MEMORY_TRACING_SUPPORTED -#endif - -namespace base { -namespace trace_event { - -// Dump provider which collects process-wide memory stats. -class BASE_EXPORT MallocDumpProvider : public MemoryDumpProvider { - public: - // Name of the allocated_objects dump. Use this to declare suballocator dumps - // from other dump providers. - static const char kAllocatedObjects[]; - - static MallocDumpProvider* GetInstance(); - - // MemoryDumpProvider implementation. - bool OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) override; - - // Used by out-of-process heap-profiling. When malloc is profiled by an - // external process, that process will be responsible for emitting metrics on - // behalf of this one. Thus, MallocDumpProvider should not do anything. - void EnableMetrics(); - void DisableMetrics(); - - private: - friend struct DefaultSingletonTraits<MallocDumpProvider>; - - MallocDumpProvider(); - ~MallocDumpProvider() override; - - bool emit_metrics_on_memory_dump_ = true; - base::Lock emit_metrics_on_memory_dump_lock_; - - DISALLOW_COPY_AND_ASSIGN(MallocDumpProvider); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc deleted file mode 100644 index 5260a73..0000000 --- a/base/trace_event/memory_allocator_dump.cc +++ /dev/null
@@ -1,148 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_allocator_dump.h" - -#include <string.h> - -#include "base/format_macros.h" -#include "base/memory/ptr_util.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/memory_dump_provider.h" -#include "base/trace_event/process_memory_dump.h" -#include "base/trace_event/trace_event_argument.h" -#include "base/values.h" - -namespace base { -namespace trace_event { - -const char MemoryAllocatorDump::kNameSize[] = "size"; -const char MemoryAllocatorDump::kNameObjectCount[] = "object_count"; -const char MemoryAllocatorDump::kTypeScalar[] = "scalar"; -const char MemoryAllocatorDump::kTypeString[] = "string"; -const char MemoryAllocatorDump::kUnitsBytes[] = "bytes"; -const char MemoryAllocatorDump::kUnitsObjects[] = "objects"; - -MemoryAllocatorDump::MemoryAllocatorDump( - const std::string& absolute_name, - MemoryDumpLevelOfDetail level_of_detail, - const MemoryAllocatorDumpGuid& guid) - : absolute_name_(absolute_name), - guid_(guid), - level_of_detail_(level_of_detail), - flags_(Flags::DEFAULT) { - // The |absolute_name| cannot be empty. - DCHECK(!absolute_name.empty()); - - // The |absolute_name| can contain slash separator, but not leading or - // trailing ones. - DCHECK(absolute_name[0] != '/' && *absolute_name.rbegin() != '/'); -} - -MemoryAllocatorDump::~MemoryAllocatorDump() = default; - -void MemoryAllocatorDump::AddScalar(const char* name, - const char* units, - uint64_t value) { - entries_.emplace_back(name, units, value); -} - -void MemoryAllocatorDump::AddString(const char* name, - const char* units, - const std::string& value) { - // String attributes are disabled in background mode. - if (level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND) { - NOTREACHED(); - return; - } - entries_.emplace_back(name, units, value); -} - -void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { - std::string string_conversion_buffer; - value->BeginDictionaryWithCopiedName(absolute_name_); - value->SetString("guid", guid_.ToString()); - value->BeginDictionary("attrs"); - - for (const Entry& entry : entries_) { - value->BeginDictionaryWithCopiedName(entry.name); - switch (entry.entry_type) { - case Entry::kUint64: - SStringPrintf(&string_conversion_buffer, "%" PRIx64, - entry.value_uint64); - value->SetString("type", kTypeScalar); - value->SetString("units", entry.units); - value->SetString("value", string_conversion_buffer); - break; - case Entry::kString: - value->SetString("type", kTypeString); - value->SetString("units", entry.units); - value->SetString("value", entry.value_string); - break; - } - value->EndDictionary(); - } - value->EndDictionary(); // "attrs": { ... } - if (flags_) - value->SetInteger("flags", flags_); - value->EndDictionary(); // "allocator_name/heap_subheap": { ... } -} - -uint64_t MemoryAllocatorDump::GetSizeInternal() const { - if (cached_size_.has_value()) - return *cached_size_; - for (const auto& entry : entries_) { - if (entry.entry_type == Entry::kUint64 && entry.units == kUnitsBytes && - strcmp(entry.name.c_str(), kNameSize) == 0) { - cached_size_ = entry.value_uint64; - return entry.value_uint64; - } - } - return 0; -}; - -MemoryAllocatorDump::Entry::Entry() : entry_type(kString), value_uint64() {} -MemoryAllocatorDump::Entry::Entry(MemoryAllocatorDump::Entry&&) noexcept = - default; -MemoryAllocatorDump::Entry& MemoryAllocatorDump::Entry::operator=( - MemoryAllocatorDump::Entry&&) = default; -MemoryAllocatorDump::Entry::Entry(std::string name, - std::string units, - uint64_t value) - : name(name), units(units), entry_type(kUint64), value_uint64(value) {} -MemoryAllocatorDump::Entry::Entry(std::string name, - std::string units, - std::string value) - : name(name), units(units), entry_type(kString), value_string(value) {} - -bool MemoryAllocatorDump::Entry::operator==(const Entry& rhs) const { - if (!(name == rhs.name && units == rhs.units && entry_type == rhs.entry_type)) - return false; - switch (entry_type) { - case EntryType::kUint64: - return value_uint64 == rhs.value_uint64; - case EntryType::kString: - return value_string == rhs.value_string; - } - NOTREACHED(); - return false; -} - -void PrintTo(const MemoryAllocatorDump::Entry& entry, std::ostream* out) { - switch (entry.entry_type) { - case MemoryAllocatorDump::Entry::EntryType::kUint64: - *out << "<Entry(\"" << entry.name << "\", \"" << entry.units << "\", " - << entry.value_uint64 << ")>"; - return; - case MemoryAllocatorDump::Entry::EntryType::kString: - *out << "<Entry(\"" << entry.name << "\", \"" << entry.units << "\", \"" - << entry.value_string << "\")>"; - return; - } - NOTREACHED(); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_allocator_dump.h b/base/trace_event/memory_allocator_dump.h deleted file mode 100644 index de38afd..0000000 --- a/base/trace_event/memory_allocator_dump.h +++ /dev/null
@@ -1,153 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ -#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ - -#include <stdint.h> - -#include <memory> -#include <ostream> -#include <string> - -#include "base/base_export.h" -#include "base/gtest_prod_util.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/optional.h" -#include "base/trace_event/memory_allocator_dump_guid.h" -#include "base/trace_event/memory_dump_request_args.h" -#include "base/trace_event/trace_event_argument.h" -#include "base/unguessable_token.h" -#include "base/values.h" - -namespace base { -namespace trace_event { - -class ProcessMemoryDump; -class TracedValue; - -// Data model for user-land memory allocator dumps. -class BASE_EXPORT MemoryAllocatorDump { - public: - enum Flags { - DEFAULT = 0, - - // A dump marked weak will be discarded by TraceViewer. - WEAK = 1 << 0, - }; - - // In the TraceViewer UI table each MemoryAllocatorDump becomes - // a row and each Entry generates a column (if it doesn't already - // exist). - struct BASE_EXPORT Entry { - enum EntryType { - kUint64, - kString, - }; - - // By design name, units and value_string are always coming from - // indefinitely lived const char* strings, the only reason we copy - // them into a std::string is to handle Mojo (de)serialization. - // TODO(hjd): Investigate optimization (e.g. using StringPiece). - Entry(); // Only for deserialization. - Entry(std::string name, std::string units, uint64_t value); - Entry(std::string name, std::string units, std::string value); - Entry(Entry&& other) noexcept; - Entry& operator=(Entry&& other); - bool operator==(const Entry& rhs) const; - - std::string name; - std::string units; - - EntryType entry_type; - - uint64_t value_uint64; - std::string value_string; - - DISALLOW_COPY_AND_ASSIGN(Entry); - }; - - MemoryAllocatorDump(const std::string& absolute_name, - MemoryDumpLevelOfDetail, - const MemoryAllocatorDumpGuid&); - ~MemoryAllocatorDump(); - - // Standard attribute |name|s for the AddScalar and AddString() methods. - static const char kNameSize[]; // To represent allocated space. - static const char kNameObjectCount[]; // To represent number of objects. - - // Standard attribute |unit|s for the AddScalar and AddString() methods. - static const char kUnitsBytes[]; // Unit name to represent bytes. - static const char kUnitsObjects[]; // Unit name to represent #objects. - - // Constants used only internally and by tests. - static const char kTypeScalar[]; // Type name for scalar attributes. - static const char kTypeString[]; // Type name for string attributes. - - // Setters for scalar attributes. Some examples: - // - "size" column (all dumps are expected to have at least this one): - // AddScalar(kNameSize, kUnitsBytes, 1234); - // - Some extra-column reporting internal details of the subsystem: - // AddScalar("number_of_freelist_entries", kUnitsObjects, 42) - // - Other informational column: - // AddString("kitten", "name", "shadow"); - void AddScalar(const char* name, const char* units, uint64_t value); - void AddString(const char* name, const char* units, const std::string& value); - - // Absolute name, unique within the scope of an entire ProcessMemoryDump. - const std::string& absolute_name() const { return absolute_name_; } - - // Called at trace generation time to populate the TracedValue. - void AsValueInto(TracedValue* value) const; - - // Get the size for this dump. - // The size is the value set with AddScalar(kNameSize, kUnitsBytes, size); - // TODO(hjd): this should return an Optional<uint64_t>. - uint64_t GetSizeInternal() const; - - MemoryDumpLevelOfDetail level_of_detail() const { return level_of_detail_; } - - // Use enum Flags to set values. - void set_flags(int flags) { flags_ |= flags; } - void clear_flags(int flags) { flags_ &= ~flags; } - int flags() const { return flags_; } - - // |guid| is an optional global dump identifier, unique across all processes - // within the scope of a global dump. It is only required when using the - // graph APIs (see TODO_method_name) to express retention / suballocation or - // cross process sharing. See crbug.com/492102 for design docs. - // Subsequent MemoryAllocatorDump(s) with the same |absolute_name| are - // expected to have the same guid. - const MemoryAllocatorDumpGuid& guid() const { return guid_; } - - const std::vector<Entry>& entries() const { return entries_; } - - // Only for mojo serialization, which can mutate the collection. - std::vector<Entry>* mutable_entries_for_serialization() const { - cached_size_.reset(); // The caller can mutate the collection. - - // Mojo takes a const input argument even for move-only types that can be - // mutate while serializing (like this one). Hence the const_cast. - return const_cast<std::vector<Entry>*>(&entries_); - } - - private: - const std::string absolute_name_; - MemoryAllocatorDumpGuid guid_; - MemoryDumpLevelOfDetail level_of_detail_; - int flags_; // See enum Flags. - mutable Optional<uint64_t> cached_size_; // Lazy, for GetSizeInternal(). - std::vector<Entry> entries_; - - DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorDump); -}; - -// This is required by gtest to print a readable output on test failures. -void BASE_EXPORT PrintTo(const MemoryAllocatorDump::Entry&, std::ostream*); - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
diff --git a/base/trace_event/memory_allocator_dump_guid.cc b/base/trace_event/memory_allocator_dump_guid.cc deleted file mode 100644 index 08ac677..0000000 --- a/base/trace_event/memory_allocator_dump_guid.cc +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_allocator_dump_guid.h" - -#include "base/format_macros.h" -#include "base/sha1.h" -#include "base/strings/stringprintf.h" - -namespace base { -namespace trace_event { - -namespace { - -uint64_t HashString(const std::string& str) { - uint64_t hash[(kSHA1Length + sizeof(uint64_t) - 1) / sizeof(uint64_t)] = {0}; - SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.data()), str.size(), - reinterpret_cast<unsigned char*>(hash)); - return hash[0]; -} - -} // namespace - -MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid(uint64_t guid) : guid_(guid) {} - -MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid() - : MemoryAllocatorDumpGuid(0u) { -} - -MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid(const std::string& guid_str) - : MemoryAllocatorDumpGuid(HashString(guid_str)) { -} - -std::string MemoryAllocatorDumpGuid::ToString() const { - return StringPrintf("%" PRIx64, guid_); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_allocator_dump_guid.h b/base/trace_event/memory_allocator_dump_guid.h deleted file mode 100644 index 2a420a2..0000000 --- a/base/trace_event/memory_allocator_dump_guid.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_GUID_H_ -#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_GUID_H_ - -#include <stdint.h> - -#include <string> - -#include "base/base_export.h" - -namespace base { -namespace trace_event { - -class BASE_EXPORT MemoryAllocatorDumpGuid { - public: - MemoryAllocatorDumpGuid(); - explicit MemoryAllocatorDumpGuid(uint64_t guid); - - // Utility ctor to hash a GUID if the caller prefers a string. The caller - // still has to ensure that |guid_str| is unique, per snapshot, within the - // global scope of all the traced processes. - explicit MemoryAllocatorDumpGuid(const std::string& guid_str); - - uint64_t ToUint64() const { return guid_; } - - // Returns a (hex-encoded) string representation of the guid. - std::string ToString() const; - - bool empty() const { return guid_ == 0u; } - - bool operator==(const MemoryAllocatorDumpGuid& other) const { - return guid_ == other.guid_; - } - - bool operator!=(const MemoryAllocatorDumpGuid& other) const { - return !(*this == other); - } - - bool operator<(const MemoryAllocatorDumpGuid& other) const { - return guid_ < other.guid_; - } - - private: - uint64_t guid_; - - // Deliberately copy-able. -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_GUID_H_
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc deleted file mode 100644 index 60ba1bb..0000000 --- a/base/trace_event/memory_dump_manager.cc +++ /dev/null
@@ -1,762 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_dump_manager.h" - -#include <inttypes.h> -#include <stdio.h> - -#include <algorithm> -#include <memory> -#include <utility> - -#include "base/base_switches.h" -#include "base/command_line.h" -#include "base/debug/alias.h" -#include "base/debug/stack_trace.h" -#include "base/debug/thread_heap_usage_tracker.h" -#include "base/memory/ptr_util.h" -#include "base/sequenced_task_runner.h" -#include "base/strings/string_util.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/trace_event/heap_profiler.h" -#include "base/trace_event/heap_profiler_allocation_context_tracker.h" -#include "base/trace_event/heap_profiler_event_filter.h" -#include "base/trace_event/heap_profiler_serialization_state.h" -#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" -#include "base/trace_event/heap_profiler_type_name_deduplicator.h" -#include "base/trace_event/malloc_dump_provider.h" -#include "base/trace_event/memory_dump_provider.h" -#include "base/trace_event/memory_dump_scheduler.h" -#include "base/trace_event/memory_infra_background_whitelist.h" -#include "base/trace_event/memory_peak_detector.h" -#include "base/trace_event/process_memory_dump.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" -#include "build_config.h" - -#if defined(OS_ANDROID) -#include "base/trace_event/java_heap_dump_provider_android.h" - -#endif // defined(OS_ANDROID) - -namespace base { -namespace trace_event { - -namespace { - -const char* const kTraceEventArgNames[] = {"dumps"}; -const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; - -MemoryDumpManager* g_memory_dump_manager_for_testing = nullptr; - -// Temporary (until peak detector and scheduler are moved outside of here) -// trampoline function to match the |request_dump_function| passed to Initialize -// to the callback expected by MemoryPeakDetector and MemoryDumpScheduler. -// TODO(primiano): remove this. -void DoGlobalDumpWithoutCallback( - MemoryDumpManager::RequestGlobalDumpFunction global_dump_fn, - MemoryDumpType dump_type, - MemoryDumpLevelOfDetail level_of_detail) { - global_dump_fn.Run(dump_type, level_of_detail); -} - -// Proxy class which wraps a ConvertableToTraceFormat owned by the -// |heap_profiler_serialization_state| into a proxy object that can be added to -// the trace event log. This is to solve the problem that the -// HeapProfilerSerializationState is refcounted but the tracing subsystem wants -// a std::unique_ptr<ConvertableToTraceFormat>. -template <typename T> -struct SessionStateConvertableProxy : public ConvertableToTraceFormat { - using GetterFunctPtr = T* (HeapProfilerSerializationState::*)() const; - - SessionStateConvertableProxy(scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state, - GetterFunctPtr getter_function) - : heap_profiler_serialization_state(heap_profiler_serialization_state), - getter_function(getter_function) {} - - void AppendAsTraceFormat(std::string* out) const override { - return (heap_profiler_serialization_state.get()->*getter_function)() - ->AppendAsTraceFormat(out); - } - - void EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) override { - return (heap_profiler_serialization_state.get()->*getter_function)() - ->EstimateTraceMemoryOverhead(overhead); - } - - scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state; - GetterFunctPtr const getter_function; -}; - -void NotifyHeapProfilingEnabledOnMDPThread( - scoped_refptr<MemoryDumpProviderInfo> mdpinfo, - bool profiling_enabled) { - mdpinfo->dump_provider->OnHeapProfilingEnabled(profiling_enabled); -} - -inline bool ShouldEnableMDPAllocatorHooks(HeapProfilingMode mode) { - return (mode == kHeapProfilingModePseudo) || - (mode == kHeapProfilingModeNative) || - (mode == kHeapProfilingModeBackground); -} - -} // namespace - -// static -const char* const MemoryDumpManager::kTraceCategory = - TRACE_DISABLED_BY_DEFAULT("memory-infra"); - -// static -const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; - -// static -const uint64_t MemoryDumpManager::kInvalidTracingProcessId = 0; - -// static -const char* const MemoryDumpManager::kSystemAllocatorPoolName = -#if defined(MALLOC_MEMORY_TRACING_SUPPORTED) - MallocDumpProvider::kAllocatedObjects; -#else - nullptr; -#endif - -// static -MemoryDumpManager* MemoryDumpManager::GetInstance() { - if (g_memory_dump_manager_for_testing) - return g_memory_dump_manager_for_testing; - - return Singleton<MemoryDumpManager, - LeakySingletonTraits<MemoryDumpManager>>::get(); -} - -// static -std::unique_ptr<MemoryDumpManager> -MemoryDumpManager::CreateInstanceForTesting() { - DCHECK(!g_memory_dump_manager_for_testing); - std::unique_ptr<MemoryDumpManager> instance(new MemoryDumpManager()); - g_memory_dump_manager_for_testing = instance.get(); - return instance; -} - -MemoryDumpManager::MemoryDumpManager() - : is_coordinator_(false), - tracing_process_id_(kInvalidTracingProcessId), - dumper_registrations_ignored_for_testing_(false), - heap_profiling_mode_(kHeapProfilingModeDisabled) {} - -MemoryDumpManager::~MemoryDumpManager() { - Thread* dump_thread = nullptr; - { - AutoLock lock(lock_); - if (dump_thread_) { - dump_thread = dump_thread_.get(); - } - } - if (dump_thread) { - dump_thread->Stop(); - } - AutoLock lock(lock_); - dump_thread_.reset(); - g_memory_dump_manager_for_testing = nullptr; -} - -bool MemoryDumpManager::EnableHeapProfiling(HeapProfilingMode profiling_mode) { - AutoLock lock(lock_); - heap_profiling_mode_ = kHeapProfilingModeInvalid; - return false; -} - -HeapProfilingMode MemoryDumpManager::GetHeapProfilingMode() { - AutoLock lock(lock_); - return heap_profiling_mode_; -} - -void MemoryDumpManager::Initialize( - RequestGlobalDumpFunction request_dump_function, - bool is_coordinator) { - { - AutoLock lock(lock_); - DCHECK(!request_dump_function.is_null()); - DCHECK(!can_request_global_dumps()); - request_dump_function_ = request_dump_function; - is_coordinator_ = is_coordinator; - } - -// Enable the core dump providers. -#if defined(MALLOC_MEMORY_TRACING_SUPPORTED) - base::trace_event::MemoryDumpProvider::Options options; - options.supports_heap_profiling = true; - RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr, - options); -#endif - -#if defined(OS_ANDROID) - RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap", - nullptr); -#endif - - TRACE_EVENT_WARMUP_CATEGORY(kTraceCategory); -} - -void MemoryDumpManager::RegisterDumpProvider( - MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SingleThreadTaskRunner> task_runner, - MemoryDumpProvider::Options options) { - options.dumps_on_single_thread_task_runner = true; - RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options); -} - -void MemoryDumpManager::RegisterDumpProvider( - MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SingleThreadTaskRunner> task_runner) { - // Set |dumps_on_single_thread_task_runner| to true because all providers - // without task runner are run on dump thread. - MemoryDumpProvider::Options options; - options.dumps_on_single_thread_task_runner = true; - RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options); -} - -void MemoryDumpManager::RegisterDumpProviderWithSequencedTaskRunner( - MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SequencedTaskRunner> task_runner, - MemoryDumpProvider::Options options) { - DCHECK(task_runner); - options.dumps_on_single_thread_task_runner = false; - RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options); -} - -void MemoryDumpManager::RegisterDumpProviderInternal( - MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SequencedTaskRunner> task_runner, - const MemoryDumpProvider::Options& options) { - if (dumper_registrations_ignored_for_testing_) - return; - - // Only a handful of MDPs are required to compute the memory metrics. These - // have small enough performance overhead that it is resonable to run them - // in the background while the user is doing other things. Those MDPs are - // 'whitelisted for background mode'. - bool whitelisted_for_background_mode = IsMemoryDumpProviderWhitelisted(name); - - scoped_refptr<MemoryDumpProviderInfo> mdpinfo = - new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options, - whitelisted_for_background_mode); - - if (options.is_fast_polling_supported) { - DCHECK(!mdpinfo->task_runner) << "MemoryDumpProviders capable of fast " - "polling must NOT be thread bound."; - } - - { - AutoLock lock(lock_); - bool already_registered = !dump_providers_.insert(mdpinfo).second; - // This actually happens in some tests which don't have a clean tear-down - // path for RenderThreadImpl::Init(). - if (already_registered) - return; - - if (options.is_fast_polling_supported) - MemoryPeakDetector::GetInstance()->NotifyMemoryDumpProvidersChanged(); - - if (ShouldEnableMDPAllocatorHooks(heap_profiling_mode_)) - NotifyHeapProfilingEnabledLocked(mdpinfo, true); - } -} - -void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { - UnregisterDumpProviderInternal(mdp, false /* delete_async */); -} - -void MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon( - std::unique_ptr<MemoryDumpProvider> mdp) { - UnregisterDumpProviderInternal(mdp.release(), true /* delete_async */); -} - -void MemoryDumpManager::UnregisterDumpProviderInternal( - MemoryDumpProvider* mdp, - bool take_mdp_ownership_and_delete_async) { - std::unique_ptr<MemoryDumpProvider> owned_mdp; - if (take_mdp_ownership_and_delete_async) - owned_mdp.reset(mdp); - - AutoLock lock(lock_); - - auto mdp_iter = dump_providers_.begin(); - for (; mdp_iter != dump_providers_.end(); ++mdp_iter) { - if ((*mdp_iter)->dump_provider == mdp) - break; - } - - if (mdp_iter == dump_providers_.end()) - return; // Not registered / already unregistered. - - if (take_mdp_ownership_and_delete_async) { - // The MDP will be deleted whenever the MDPInfo struct will, that is either: - // - At the end of this function, if no dump is in progress. - // - In ContinueAsyncProcessDump() when MDPInfo is removed from - // |pending_dump_providers|. - // - When the provider is removed from other clients (MemoryPeakDetector). - DCHECK(!(*mdp_iter)->owned_dump_provider); - (*mdp_iter)->owned_dump_provider = std::move(owned_mdp); - } else { - // If you hit this DCHECK, your dump provider has a bug. - // Unregistration of a MemoryDumpProvider is safe only if: - // - The MDP has specified a sequenced task runner affinity AND the - // unregistration happens on the same task runner. So that the MDP cannot - // unregister and be in the middle of a OnMemoryDump() at the same time. - // - The MDP has NOT specified a task runner affinity and its ownership is - // transferred via UnregisterAndDeleteDumpProviderSoon(). - // In all the other cases, it is not possible to guarantee that the - // unregistration will not race with OnMemoryDump() calls. - DCHECK((*mdp_iter)->task_runner && - (*mdp_iter)->task_runner->RunsTasksInCurrentSequence()) - << "MemoryDumpProvider \"" << (*mdp_iter)->name << "\" attempted to " - << "unregister itself in a racy way. Please file a crbug."; - } - - if ((*mdp_iter)->options.is_fast_polling_supported) { - DCHECK(take_mdp_ownership_and_delete_async); - MemoryPeakDetector::GetInstance()->NotifyMemoryDumpProvidersChanged(); - } - - // The MDPInfo instance can still be referenced by the - // |ProcessMemoryDumpAsyncState.pending_dump_providers|. For this reason - // the MDPInfo is flagged as disabled. It will cause InvokeOnMemoryDump() - // to just skip it, without actually invoking the |mdp|, which might be - // destroyed by the caller soon after this method returns. - (*mdp_iter)->disabled = true; - dump_providers_.erase(mdp_iter); -} - -void MemoryDumpManager::GetDumpProvidersForPolling( - std::vector<scoped_refptr<MemoryDumpProviderInfo>>* providers) { - DCHECK(providers->empty()); - AutoLock lock(lock_); - for (const scoped_refptr<MemoryDumpProviderInfo>& mdp : dump_providers_) { - if (mdp->options.is_fast_polling_supported) - providers->push_back(mdp); - } -} - -bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( - MemoryDumpProvider* provider) { - AutoLock lock(lock_); - - for (const auto& info : dump_providers_) { - if (info->dump_provider == provider) - return true; - } - return false; -} - -scoped_refptr<base::SequencedTaskRunner> -MemoryDumpManager::GetOrCreateBgTaskRunnerLocked() { - lock_.AssertAcquired(); - - if (dump_thread_) - return dump_thread_->task_runner(); - - dump_thread_ = std::make_unique<Thread>("MemoryInfra"); - bool started = dump_thread_->Start(); - CHECK(started); - - return dump_thread_->task_runner(); -} - -void MemoryDumpManager::CreateProcessDump( - const MemoryDumpRequestArgs& args, - const ProcessMemoryDumpCallback& callback) { - char guid_str[20]; - sprintf(guid_str, "0x%" PRIx64, args.dump_guid); - TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", - TRACE_ID_LOCAL(args.dump_guid), "dump_guid", - TRACE_STR_COPY(guid_str)); - - // If argument filter is enabled then only background mode dumps should be - // allowed. In case the trace config passed for background tracing session - // missed the allowed modes argument, it crashes here instead of creating - // unexpected dumps. - if (TraceLog::GetInstance() - ->GetCurrentTraceConfig() - .IsArgumentFilterEnabled()) { - CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); - } - - std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; - { - AutoLock lock(lock_); - - // MDM could have been disabled by this point destroying - // |heap_profiler_serialization_state|. If heap profiling is enabled we - // require session state so if heap profiling is on and session state is - // absent we fail the dump immediately. If heap profiler is enabled during - // the dump, then the dump succeeds since the dump was requested before, and - // the future process dumps will contain heap dumps. - if (args.dump_type != MemoryDumpType::SUMMARY_ONLY && - ShouldEnableMDPAllocatorHooks(heap_profiling_mode_) && - !heap_profiler_serialization_state_) { - callback.Run(false /* success */, args.dump_guid, nullptr); - return; - } - - pmd_async_state.reset(new ProcessMemoryDumpAsyncState( - args, dump_providers_, heap_profiler_serialization_state_, callback, - GetOrCreateBgTaskRunnerLocked())); - - // If enabled, holds back the peak detector resetting its estimation window. - MemoryPeakDetector::GetInstance()->Throttle(); - } - - // Start the process dump. This involves task runner hops as specified by the - // MemoryDumpProvider(s) in RegisterDumpProvider()). - ContinueAsyncProcessDump(pmd_async_state.release()); -} - -// Invokes OnMemoryDump() on all MDPs that are next in the pending list and run -// on the current sequenced task runner. If the next MDP does not run in current -// sequenced task runner, then switches to that task runner and continues. All -// OnMemoryDump() invocations are linearized. |lock_| is used in these functions -// purely to ensure consistency w.r.t. (un)registrations of |dump_providers_|. -void MemoryDumpManager::ContinueAsyncProcessDump( - ProcessMemoryDumpAsyncState* owned_pmd_async_state) { - HEAP_PROFILER_SCOPED_IGNORE; - // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs - // in the PostTask below don't end up registering their own dump providers - // (for discounting trace memory overhead) while holding the |lock_|. - TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); - - // In theory |owned_pmd_async_state| should be a unique_ptr. The only reason - // why it isn't is because of the corner case logic of |did_post_task| - // above, which needs to take back the ownership of the |pmd_async_state| when - // the PostTask() fails. - // Unfortunately, PostTask() destroys the unique_ptr arguments upon failure - // to prevent accidental leaks. Using a unique_ptr would prevent us to to - // skip the hop and move on. Hence the manual naked -> unique ptr juggling. - auto pmd_async_state = WrapUnique(owned_pmd_async_state); - owned_pmd_async_state = nullptr; - - while (!pmd_async_state->pending_dump_providers.empty()) { - // Read MemoryDumpProviderInfo thread safety considerations in - // memory_dump_manager.h when accessing |mdpinfo| fields. - MemoryDumpProviderInfo* mdpinfo = - pmd_async_state->pending_dump_providers.back().get(); - - // If we are in background mode, we should invoke only the whitelisted - // providers. Ignore other providers and continue. - if (pmd_async_state->req_args.level_of_detail == - MemoryDumpLevelOfDetail::BACKGROUND && - !mdpinfo->whitelisted_for_background_mode) { - pmd_async_state->pending_dump_providers.pop_back(); - continue; - } - - // If the dump provider did not specify a task runner affinity, dump on - // |dump_thread_|. - scoped_refptr<SequencedTaskRunner> task_runner = mdpinfo->task_runner; - if (!task_runner) { - DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner); - task_runner = pmd_async_state->dump_thread_task_runner; - DCHECK(task_runner); - } - - // If |RunsTasksInCurrentSequence()| is true then no PostTask is - // required since we are on the right SequencedTaskRunner. - if (task_runner->RunsTasksInCurrentSequence()) { - InvokeOnMemoryDump(mdpinfo, pmd_async_state->process_memory_dump.get()); - pmd_async_state->pending_dump_providers.pop_back(); - continue; - } - - bool did_post_task = task_runner->PostTask( - FROM_HERE, - BindOnce(&MemoryDumpManager::ContinueAsyncProcessDump, Unretained(this), - Unretained(pmd_async_state.get()))); - - if (did_post_task) { - // Ownership is tranferred to the posted task. - ignore_result(pmd_async_state.release()); - return; - } - - // PostTask usually fails only if the process or thread is shut down. So, - // the dump provider is disabled here. But, don't disable unbound dump - // providers, since the |dump_thread_| is controlled by MDM. - if (mdpinfo->task_runner) { - // A locked access is required to R/W |disabled| (for the - // UnregisterAndDeleteDumpProviderSoon() case). - AutoLock lock(lock_); - mdpinfo->disabled = true; - } - - // PostTask failed. Ignore the dump provider and continue. - pmd_async_state->pending_dump_providers.pop_back(); - } - - FinishAsyncProcessDump(std::move(pmd_async_state)); -} - -// This function is called on the right task runner for current MDP. It is -// either the task runner specified by MDP or |dump_thread_task_runner| if the -// MDP did not specify task runner. Invokes the dump provider's OnMemoryDump() -// (unless disabled). -void MemoryDumpManager::InvokeOnMemoryDump(MemoryDumpProviderInfo* mdpinfo, - ProcessMemoryDump* pmd) { - HEAP_PROFILER_SCOPED_IGNORE; - DCHECK(!mdpinfo->task_runner || - mdpinfo->task_runner->RunsTasksInCurrentSequence()); - - TRACE_EVENT1(kTraceCategory, "MemoryDumpManager::InvokeOnMemoryDump", - "dump_provider.name", mdpinfo->name); - - // Do not add any other TRACE_EVENT macro (or function that might have them) - // below this point. Under some rare circunstances, they can re-initialize - // and invalide the current ThreadLocalEventBuffer MDP, making the - // |should_dump| check below susceptible to TOCTTOU bugs - // (https://crbug.com/763365). - - bool is_thread_bound; - { - // A locked access is required to R/W |disabled| (for the - // UnregisterAndDeleteDumpProviderSoon() case). - AutoLock lock(lock_); - - // Unregister the dump provider if it failed too many times consecutively. - if (!mdpinfo->disabled && - mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) { - mdpinfo->disabled = true; - DLOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name - << "\". Dump failed multiple times consecutively."; - } - if (mdpinfo->disabled) - return; - - is_thread_bound = mdpinfo->task_runner != nullptr; - } // AutoLock lock(lock_); - - // Invoke the dump provider. - - // A stack allocated string with dump provider name is useful to debug - // crashes while invoking dump after a |dump_provider| is not unregistered - // in safe way. - char provider_name_for_debugging[16]; - strncpy(provider_name_for_debugging, mdpinfo->name, - sizeof(provider_name_for_debugging) - 1); - provider_name_for_debugging[sizeof(provider_name_for_debugging) - 1] = '\0'; - base::debug::Alias(provider_name_for_debugging); - - ANNOTATE_BENIGN_RACE(&mdpinfo->disabled, "best-effort race detection"); - CHECK(!is_thread_bound || - !*(static_cast<volatile bool*>(&mdpinfo->disabled))); - bool dump_successful = - mdpinfo->dump_provider->OnMemoryDump(pmd->dump_args(), pmd); - mdpinfo->consecutive_failures = - dump_successful ? 0 : mdpinfo->consecutive_failures + 1; -} - -void MemoryDumpManager::FinishAsyncProcessDump( - std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { - HEAP_PROFILER_SCOPED_IGNORE; - DCHECK(pmd_async_state->pending_dump_providers.empty()); - const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; - if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { - scoped_refptr<SingleThreadTaskRunner> callback_task_runner = - pmd_async_state->callback_task_runner; - callback_task_runner->PostTask( - FROM_HERE, BindOnce(&MemoryDumpManager::FinishAsyncProcessDump, - Unretained(this), std::move(pmd_async_state))); - return; - } - - TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinishAsyncProcessDump"); - - // In the general case (allocators and edges) the serialization into the trace - // buffer is handled by the memory-infra service (see tracing_observer.cc). - // This special case below deals only with serialization of the heap profiler - // and is temporary given the upcoming work on the out-of-process heap - // profiler. - const auto& args = pmd_async_state->req_args; - if (!pmd_async_state->process_memory_dump->heap_dumps().empty()) { - std::unique_ptr<TracedValue> traced_value = std::make_unique<TracedValue>(); - pmd_async_state->process_memory_dump->SerializeHeapProfilerDumpsInto( - traced_value.get()); - - traced_value->SetString("level_of_detail", - base::trace_event::MemoryDumpLevelOfDetailToString( - args.level_of_detail)); - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> event_value( - std::move(traced_value)); - TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( - TRACE_EVENT_PHASE_MEMORY_DUMP, - base::trace_event::TraceLog::GetCategoryGroupEnabled( - base::trace_event::MemoryDumpManager::kTraceCategory), - base::trace_event::MemoryDumpTypeToString(args.dump_type), - trace_event_internal::kGlobalScope, args.dump_guid, - base::kNullProcessId, 1 /* num_args */, kTraceEventArgNames, - kTraceEventArgTypes, nullptr /* arg_values */, &event_value, - TRACE_EVENT_FLAG_HAS_ID); - } - - if (!pmd_async_state->callback.is_null()) { - pmd_async_state->callback.Run( - true /* success */, dump_guid, - std::move(pmd_async_state->process_memory_dump)); - pmd_async_state->callback.Reset(); - } - - TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", - TRACE_ID_LOCAL(dump_guid)); -} - -void MemoryDumpManager::SetupForTracing( - const TraceConfig::MemoryDumpConfig& memory_dump_config) { - AutoLock lock(lock_); - heap_profiler_serialization_state_ = new HeapProfilerSerializationState(); - heap_profiler_serialization_state_ - ->set_heap_profiler_breakdown_threshold_bytes( - memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); - InitializeHeapProfilerStateIfNeededLocked(); - - // At this point we must have the ability to request global dumps. - DCHECK(can_request_global_dumps()); - - MemoryDumpScheduler::Config periodic_config; - bool peak_detector_configured = false; - for (const auto& trigger : memory_dump_config.triggers) { - if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { - if (periodic_config.triggers.empty()) { - periodic_config.callback = - BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_, - MemoryDumpType::PERIODIC_INTERVAL); - } - periodic_config.triggers.push_back( - {trigger.level_of_detail, trigger.min_time_between_dumps_ms}); - } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { - // At most one peak trigger is allowed. - CHECK(!peak_detector_configured); - peak_detector_configured = true; - MemoryPeakDetector::GetInstance()->Setup( - BindRepeating(&MemoryDumpManager::GetDumpProvidersForPolling, - Unretained(this)), - GetOrCreateBgTaskRunnerLocked(), - BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_, - MemoryDumpType::PEAK_MEMORY_USAGE, - trigger.level_of_detail)); - - MemoryPeakDetector::Config peak_config; - peak_config.polling_interval_ms = 10; - peak_config.min_time_between_peaks_ms = trigger.min_time_between_dumps_ms; - peak_config.enable_verbose_poll_tracing = - trigger.level_of_detail == MemoryDumpLevelOfDetail::DETAILED; - MemoryPeakDetector::GetInstance()->Start(peak_config); - - // When peak detection is enabled, trigger a dump straight away as it - // gives a good reference point for analyzing the trace. - if (is_coordinator_) { - GetOrCreateBgTaskRunnerLocked()->PostTask( - FROM_HERE, - BindOnce(&DoGlobalDumpWithoutCallback, request_dump_function_, - MemoryDumpType::PEAK_MEMORY_USAGE, - trigger.level_of_detail)); - } - } - } - - // Only coordinator process triggers periodic memory dumps. - if (is_coordinator_ && !periodic_config.triggers.empty()) { - MemoryDumpScheduler::GetInstance()->Start(periodic_config, - GetOrCreateBgTaskRunnerLocked()); - } -} - -void MemoryDumpManager::TeardownForTracing() { - // There might be a memory dump in progress while this happens. Therefore, - // ensure that the MDM state which depends on the tracing enabled / disabled - // state is always accessed by the dumping methods holding the |lock_|. - AutoLock lock(lock_); - - MemoryDumpScheduler::GetInstance()->Stop(); - MemoryPeakDetector::GetInstance()->TearDown(); - heap_profiler_serialization_state_ = nullptr; -} - -void MemoryDumpManager::InitializeHeapProfilerStateIfNeededLocked() { - lock_.AssertAcquired(); - if (!ShouldEnableMDPAllocatorHooks(heap_profiling_mode_) || - !heap_profiler_serialization_state_ || - heap_profiler_serialization_state_->is_initialized()) { - return; - } - // If heap profiling is enabled, the stack frame deduplicator and type name - // deduplicator will be in use. Add a metadata events to write the frames - // and type IDs. - heap_profiler_serialization_state_->SetStackFrameDeduplicator( - WrapUnique(new StackFrameDeduplicator)); - heap_profiler_serialization_state_->SetTypeNameDeduplicator( - WrapUnique(new TypeNameDeduplicator)); - - TRACE_EVENT_API_ADD_METADATA_EVENT( - TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames", - "stackFrames", - std::make_unique<SessionStateConvertableProxy<StackFrameDeduplicator>>( - heap_profiler_serialization_state_, - &HeapProfilerSerializationState::stack_frame_deduplicator)); - - TRACE_EVENT_API_ADD_METADATA_EVENT( - TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", "typeNames", - std::make_unique<SessionStateConvertableProxy<TypeNameDeduplicator>>( - heap_profiler_serialization_state_, - &HeapProfilerSerializationState::type_name_deduplicator)); -} - -void MemoryDumpManager::NotifyHeapProfilingEnabledLocked( - scoped_refptr<MemoryDumpProviderInfo> mdpinfo, - bool enabled) { - lock_.AssertAcquired(); - if (!mdpinfo->options.supports_heap_profiling) - return; - - const auto& task_runner = mdpinfo->task_runner - ? mdpinfo->task_runner - : GetOrCreateBgTaskRunnerLocked(); - // TODO(ssid): Post tasks only for MDPs that support heap profiling. - task_runner->PostTask( - FROM_HERE, - BindOnce(&NotifyHeapProfilingEnabledOnMDPThread, mdpinfo, enabled)); -} - -MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( - MemoryDumpRequestArgs req_args, - const MemoryDumpProviderInfo::OrderedSet& dump_providers, - scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state_in, - ProcessMemoryDumpCallback callback, - scoped_refptr<SequencedTaskRunner> dump_thread_task_runner) - : req_args(req_args), - heap_profiler_serialization_state( - std::move(heap_profiler_serialization_state_in)), - callback(callback), - callback_task_runner(ThreadTaskRunnerHandle::Get()), - dump_thread_task_runner(std::move(dump_thread_task_runner)) { - pending_dump_providers.reserve(dump_providers.size()); - pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); - MemoryDumpArgs args = {req_args.level_of_detail, req_args.dump_guid}; - process_memory_dump = std::make_unique<ProcessMemoryDump>( - heap_profiler_serialization_state, args); -} - -MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() = - default; - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h deleted file mode 100644 index 072a7d6..0000000 --- a/base/trace_event/memory_dump_manager.h +++ /dev/null
@@ -1,320 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ -#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_ - -#include <stdint.h> - -#include <map> -#include <memory> -#include <unordered_set> -#include <vector> - -#include "base/atomicops.h" -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/memory_dump_provider_info.h" -#include "base/trace_event/memory_dump_request_args.h" -#include "base/trace_event/process_memory_dump.h" -#include "base/trace_event/trace_event.h" - -namespace base { - -class SequencedTaskRunner; -class SingleThreadTaskRunner; -class Thread; - -namespace trace_event { - -class MemoryDumpProvider; -class HeapProfilerSerializationState; - -enum HeapProfilingMode { - kHeapProfilingModeDisabled, - kHeapProfilingModeTaskProfiler, // Per task counters for allocs and frees. - kHeapProfilingModeBackground, // Pseudo stacks without default filtering. - kHeapProfilingModePseudo, // Pseudo stacks with default filtering categories. - kHeapProfilingModeNative, // Native stacks - kHeapProfilingModeInvalid // Disabled permanently or unsupported. -}; - -// This is the interface exposed to the rest of the codebase to deal with -// memory tracing. The main entry point for clients is represented by -// RequestDumpPoint(). The extension by Un(RegisterDumpProvider). -class BASE_EXPORT MemoryDumpManager { - public: - using RequestGlobalDumpFunction = - RepeatingCallback<void(MemoryDumpType, MemoryDumpLevelOfDetail)>; - - static const char* const kTraceCategory; - - // This value is returned as the tracing id of the child processes by - // GetTracingProcessId() when tracing is not enabled. - static const uint64_t kInvalidTracingProcessId; - - static MemoryDumpManager* GetInstance(); - static std::unique_ptr<MemoryDumpManager> CreateInstanceForTesting(); - - // Invoked once per process to listen to trace begin / end events. - // Initialization can happen after (Un)RegisterMemoryDumpProvider() calls - // and the MemoryDumpManager guarantees to support this. - // On the other side, the MemoryDumpManager will not be fully operational - // (any CreateProcessDump() will return a failure) until initialized. - // Arguments: - // is_coordinator: True when current process coordinates the periodic dump - // triggering. - // request_dump_function: Function to invoke a global dump. Global dump - // involves embedder-specific behaviors like multiprocess handshaking. - // TODO(primiano): this is only required to trigger global dumps from - // the scheduler and the peak detector. Should be removed once they are - // both moved out of base. - void Initialize(RequestGlobalDumpFunction request_dump_function, - bool is_coordinator); - - // (Un)Registers a MemoryDumpProvider instance. - // Args: - // - mdp: the MemoryDumpProvider instance to be registered. MemoryDumpManager - // does NOT take memory ownership of |mdp|, which is expected to either - // be a singleton or unregister itself. - // - name: a friendly name (duplicates allowed). Used for debugging and - // run-time profiling of memory-infra internals. Must be a long-lived - // C string. - // - task_runner: either a SingleThreadTaskRunner or SequencedTaskRunner. All - // the calls to |mdp| will be run on the given |task_runner|. If passed - // null |mdp| should be able to handle calls on arbitrary threads. - // - options: extra optional arguments. See memory_dump_provider.h. - void RegisterDumpProvider(MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SingleThreadTaskRunner> task_runner); - void RegisterDumpProvider(MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SingleThreadTaskRunner> task_runner, - MemoryDumpProvider::Options options); - void RegisterDumpProviderWithSequencedTaskRunner( - MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SequencedTaskRunner> task_runner, - MemoryDumpProvider::Options options); - void UnregisterDumpProvider(MemoryDumpProvider* mdp); - - // Unregisters an unbound dump provider and takes care about its deletion - // asynchronously. Can be used only for for dump providers with no - // task-runner affinity. - // This method takes ownership of the dump provider and guarantees that: - // - The |mdp| will be deleted at some point in the near future. - // - Its deletion will not happen concurrently with the OnMemoryDump() call. - // Note that OnMemoryDump() and PollFastMemoryTotal() calls can still happen - // after this method returns. - void UnregisterAndDeleteDumpProviderSoon( - std::unique_ptr<MemoryDumpProvider> mdp); - - // Prepare MemoryDumpManager for CreateProcessDump() calls for tracing-related - // modes (i.e. |level_of_detail| != SUMMARY_ONLY). - // Also initializes the peak detector, scheduler and heap profiler with the - // given config. - void SetupForTracing(const TraceConfig::MemoryDumpConfig&); - - // Tear-down tracing related state. - // Non-tracing modes (e.g. SUMMARY_ONLY) will continue to work. - void TeardownForTracing(); - - // Creates a memory dump for the current process and appends it to the trace. - // |callback| will be invoked asynchronously upon completion on the same - // thread on which CreateProcessDump() was called. This method should only be - // used by the memory-infra service while creating a global memory dump. - void CreateProcessDump(const MemoryDumpRequestArgs& args, - const ProcessMemoryDumpCallback& callback); - - // Enable heap profiling with specified |profiling_mode|. - // Use kHeapProfilingModeDisabled to disable, but it can't be re-enabled then. - // Returns true if mode has been *changed* to the desired |profiling_mode|. - bool EnableHeapProfiling(HeapProfilingMode profiling_mode); - HeapProfilingMode GetHeapProfilingMode(); - - // Lets tests see if a dump provider is registered. - bool IsDumpProviderRegisteredForTesting(MemoryDumpProvider*); - - const scoped_refptr<HeapProfilerSerializationState>& - heap_profiler_serialization_state_for_testing() const { - return heap_profiler_serialization_state_; - } - - // Returns a unique id for identifying the processes. The id can be - // retrieved by child processes only when tracing is enabled. This is - // intended to express cross-process sharing of memory dumps on the - // child-process side, without having to know its own child process id. - uint64_t GetTracingProcessId() const { return tracing_process_id_; } - void set_tracing_process_id(uint64_t tracing_process_id) { - tracing_process_id_ = tracing_process_id; - } - - // Returns the name for a the allocated_objects dump. Use this to declare - // suballocator dumps from other dump providers. - // It will return nullptr if there is no dump provider for the system - // allocator registered (which is currently the case for Mac OS). - const char* system_allocator_pool_name() const { - return kSystemAllocatorPoolName; - }; - - // When set to true, calling |RegisterMemoryDumpProvider| is a no-op. - void set_dumper_registrations_ignored_for_testing(bool ignored) { - dumper_registrations_ignored_for_testing_ = ignored; - } - - private: - friend std::default_delete<MemoryDumpManager>; // For the testing instance. - friend struct DefaultSingletonTraits<MemoryDumpManager>; - friend class MemoryDumpManagerTest; - FRIEND_TEST_ALL_PREFIXES(MemoryDumpManagerTest, - NoStackOverflowWithTooManyMDPs); - - // Holds the state of a process memory dump that needs to be carried over - // across task runners in order to fulfill an asynchronous CreateProcessDump() - // request. At any time exactly one task runner owns a - // ProcessMemoryDumpAsyncState. - struct ProcessMemoryDumpAsyncState { - ProcessMemoryDumpAsyncState( - MemoryDumpRequestArgs req_args, - const MemoryDumpProviderInfo::OrderedSet& dump_providers, - scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state, - ProcessMemoryDumpCallback callback, - scoped_refptr<SequencedTaskRunner> dump_thread_task_runner); - ~ProcessMemoryDumpAsyncState(); - - // A ProcessMemoryDump to collect data from MemoryDumpProviders. - std::unique_ptr<ProcessMemoryDump> process_memory_dump; - - // The arguments passed to the initial CreateProcessDump() request. - const MemoryDumpRequestArgs req_args; - - // An ordered sequence of dump providers that have to be invoked to complete - // the dump. This is a copy of |dump_providers_| at the beginning of a dump - // and becomes empty at the end, when all dump providers have been invoked. - std::vector<scoped_refptr<MemoryDumpProviderInfo>> pending_dump_providers; - - // The HeapProfilerSerializationState object, which is shared by all - // the ProcessMemoryDump and MemoryAllocatorDump instances through all the - // tracing session lifetime. - scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state; - - // Callback passed to the initial call to CreateProcessDump(). - ProcessMemoryDumpCallback callback; - - // The thread on which FinishAsyncProcessDump() (and hence |callback|) - // should be invoked. This is the thread on which the initial - // CreateProcessDump() request was called. - const scoped_refptr<SingleThreadTaskRunner> callback_task_runner; - - // The thread on which unbound dump providers should be invoked. - // This is essentially |dump_thread_|.task_runner() but needs to be kept - // as a separate variable as it needs to be accessed by arbitrary dumpers' - // threads outside of the lock_ to avoid races when disabling tracing. - // It is immutable for all the duration of a tracing session. - const scoped_refptr<SequencedTaskRunner> dump_thread_task_runner; - - private: - DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpAsyncState); - }; - - static const int kMaxConsecutiveFailuresCount; - static const char* const kSystemAllocatorPoolName; - - MemoryDumpManager(); - virtual ~MemoryDumpManager(); - - static void SetInstanceForTesting(MemoryDumpManager* instance); - - // Lazily initializes dump_thread_ and returns its TaskRunner. - scoped_refptr<base::SequencedTaskRunner> GetOrCreateBgTaskRunnerLocked(); - - // Calls InvokeOnMemoryDump() for the each MDP that belongs to the current - // task runner and switches to the task runner of the next MDP. Handles - // failures in MDP and thread hops, and always calls FinishAsyncProcessDump() - // at the end. - void ContinueAsyncProcessDump( - ProcessMemoryDumpAsyncState* owned_pmd_async_state); - - // Invokes OnMemoryDump() of the given MDP. Should be called on the MDP task - // runner. - void InvokeOnMemoryDump(MemoryDumpProviderInfo* mdpinfo, - ProcessMemoryDump* pmd); - - void FinishAsyncProcessDump( - std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state); - - // Helper for RegierDumpProvider* functions. - void RegisterDumpProviderInternal( - MemoryDumpProvider* mdp, - const char* name, - scoped_refptr<SequencedTaskRunner> task_runner, - const MemoryDumpProvider::Options& options); - - // Helper for the public UnregisterDumpProvider* functions. - void UnregisterDumpProviderInternal(MemoryDumpProvider* mdp, - bool take_mdp_ownership_and_delete_async); - - // Fills the passed vector with the subset of dump providers which were - // registered with is_fast_polling_supported == true. - void GetDumpProvidersForPolling( - std::vector<scoped_refptr<MemoryDumpProviderInfo>>*); - - // Initialize |heap_profiler_serialization_state_| when tracing and heap - // profiler are enabled. - void InitializeHeapProfilerStateIfNeededLocked(); - - // Sends OnHeapProfilingEnabled() notifcation to mdp ensuring OnMemoryDump() - // is not called at the same time. - void NotifyHeapProfilingEnabledLocked( - scoped_refptr<MemoryDumpProviderInfo> mdpinfo, - bool enabled); - - bool can_request_global_dumps() const { - return !request_dump_function_.is_null(); - } - - // An ordered set of registered MemoryDumpProviderInfo(s), sorted by task - // runner affinity (MDPs belonging to the same task runners are adjacent). - MemoryDumpProviderInfo::OrderedSet dump_providers_; - - // Shared among all the PMDs to keep state scoped to the tracing session. - scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state_; - - // Function provided by the embedder to handle global dump requests. - RequestGlobalDumpFunction request_dump_function_; - - // True when current process coordinates the periodic dump triggering. - bool is_coordinator_; - - // Protects from concurrent accesses to the local state, eg: to guard against - // disabling logging while dumping on another thread. - Lock lock_; - - // Thread used for MemoryDumpProviders which don't specify a task runner - // affinity. - std::unique_ptr<Thread> dump_thread_; - - // The unique id of the child process. This is created only for tracing and is - // expected to be valid only when tracing is enabled. - uint64_t tracing_process_id_; - - // When true, calling |RegisterMemoryDumpProvider| is a no-op. - bool dumper_registrations_ignored_for_testing_; - - HeapProfilingMode heap_profiling_mode_; - - DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
diff --git a/base/trace_event/memory_dump_manager_test_utils.h b/base/trace_event/memory_dump_manager_test_utils.h deleted file mode 100644 index 413017f..0000000 --- a/base/trace_event/memory_dump_manager_test_utils.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_TEST_UTILS_H_ -#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_TEST_UTILS_H_ - -#include "base/bind.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/memory_dump_request_args.h" - -namespace base { -namespace trace_event { - -void RequestGlobalDumpForInProcessTesting( - base::trace_event::MemoryDumpType dump_type, - base::trace_event::MemoryDumpLevelOfDetail level_of_detail) { - MemoryDumpRequestArgs local_args = {0 /* dump_guid */, dump_type, - level_of_detail}; - MemoryDumpManager::GetInstance()->CreateProcessDump( - local_args, ProcessMemoryDumpCallback()); -}; - -// Short circuits the RequestGlobalDumpFunction() to CreateProcessDump(), -// effectively allowing to use both in unittests with the same behavior. -// Unittests are in-process only and don't require all the multi-process -// dump handshaking (which would require bits outside of base). -void InitializeMemoryDumpManagerForInProcessTesting(bool is_coordinator) { - MemoryDumpManager* instance = MemoryDumpManager::GetInstance(); - instance->set_dumper_registrations_ignored_for_testing(true); - instance->Initialize(BindRepeating(&RequestGlobalDumpForInProcessTesting), - is_coordinator); -} - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_TEST_UTILS_H_
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h deleted file mode 100644 index b458bfb..0000000 --- a/base/trace_event/memory_dump_provider.h +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_ -#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_ - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/process/process_handle.h" -#include "base/trace_event/memory_dump_request_args.h" - -namespace base { -namespace trace_event { - -class ProcessMemoryDump; - -// The contract interface that memory dump providers must implement. -class BASE_EXPORT MemoryDumpProvider { - public: - // Optional arguments for MemoryDumpManager::RegisterDumpProvider(). - struct Options { - Options() - : dumps_on_single_thread_task_runner(false), - is_fast_polling_supported(false), - supports_heap_profiling(false) {} - - // |dumps_on_single_thread_task_runner| is true if the dump provider runs on - // a SingleThreadTaskRunner, which is usually the case. It is faster to run - // all providers that run on the same thread together without thread hops. - bool dumps_on_single_thread_task_runner; - - // Set to true if the dump provider implementation supports high frequency - // polling. Only providers running without task runner affinity are - // supported. - bool is_fast_polling_supported; - - // Set to true when the dump provider supports heap profiling. MDM sends - // OnHeapProfiling() notifications only if this is set to true. - bool supports_heap_profiling; - }; - - virtual ~MemoryDumpProvider() = default; - - // Called by the MemoryDumpManager when generating memory dumps. - // The |args| specify if the embedder should generate light/heavy dumps on - // dump requests. The embedder should return true if the |pmd| was - // successfully populated, false if something went wrong and the dump should - // be considered invalid. - // (Note, the MemoryDumpManager has a fail-safe logic which will disable the - // MemoryDumpProvider for the entire trace session if it fails consistently). - virtual bool OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) = 0; - - // Called by the MemoryDumpManager when an allocator should start or stop - // collecting extensive allocation data, if supported. Called only when - // |supports_heap_profiling| is set to true. - virtual void OnHeapProfilingEnabled(bool enabled) {} - - // Quickly record the total memory usage in |memory_total|. This method will - // be called only when the dump provider registration has - // |is_fast_polling_supported| set to true. This method is used for polling at - // high frequency for detecting peaks. See comment on - // |is_fast_polling_supported| option if you need to override this method. - virtual void PollFastMemoryTotal(uint64_t* memory_total) {} - - // Indicates that fast memory polling is not going to be used in the near - // future and the MDP can tear down any resource kept around for fast memory - // polling. - virtual void SuspendFastMemoryPolling() {} - - protected: - MemoryDumpProvider() = default; - - DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
diff --git a/base/trace_event/memory_dump_provider_info.cc b/base/trace_event/memory_dump_provider_info.cc deleted file mode 100644 index 3220476..0000000 --- a/base/trace_event/memory_dump_provider_info.cc +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_dump_provider_info.h" - -#include <tuple> - -#include "base/sequenced_task_runner.h" - -namespace base { -namespace trace_event { - -MemoryDumpProviderInfo::MemoryDumpProviderInfo( - MemoryDumpProvider* dump_provider, - const char* name, - scoped_refptr<SequencedTaskRunner> task_runner, - const MemoryDumpProvider::Options& options, - bool whitelisted_for_background_mode) - : dump_provider(dump_provider), - options(options), - name(name), - task_runner(std::move(task_runner)), - whitelisted_for_background_mode(whitelisted_for_background_mode), - consecutive_failures(0), - disabled(false) {} - -MemoryDumpProviderInfo::~MemoryDumpProviderInfo() = default; - -bool MemoryDumpProviderInfo::Comparator::operator()( - const scoped_refptr<MemoryDumpProviderInfo>& a, - const scoped_refptr<MemoryDumpProviderInfo>& b) const { - if (!a || !b) - return a.get() < b.get(); - // Ensure that unbound providers (task_runner == nullptr) always run last. - // Rationale: some unbound dump providers are known to be slow, keep them last - // to avoid skewing timings of the other dump providers. - return std::tie(a->task_runner, a->dump_provider) > - std::tie(b->task_runner, b->dump_provider); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_dump_provider_info.h b/base/trace_event/memory_dump_provider_info.h deleted file mode 100644 index f0ea1e6..0000000 --- a/base/trace_event/memory_dump_provider_info.h +++ /dev/null
@@ -1,108 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_INFO_H_ -#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_INFO_H_ - -#include <memory> -#include <set> - -#include "base/base_export.h" -#include "base/memory/ref_counted.h" -#include "base/trace_event/memory_dump_provider.h" - -namespace base { - -class SequencedTaskRunner; - -namespace trace_event { - -// Wraps a MemoryDumpProvider (MDP), which is registered via -// MemoryDumpManager(MDM)::RegisterDumpProvider(), holding the extra information -// required to deal with it (which task runner it should be invoked onto, -// whether it has been disabled, etc.) -// More importantly, having a refptr to this object guarantees that a MDP that -// is not thread-bound (hence which can only be unregistered via -// MDM::UnregisterAndDeleteDumpProviderSoon()) will stay alive as long as the -// refptr is held. -// -// Lifetime: -// At any time, there is at most one instance of this class for each instance -// of a given MemoryDumpProvider, but there might be several scoped_refptr -// holding onto each of this. Specifically: -// - In nominal conditions, there is a refptr for each registered MDP in the -// MDM's |dump_providers_| list. -// - In most cases, the only refptr (in the |dump_providers_| list) is destroyed -// by MDM::UnregisterDumpProvider(). -// - However, when MDM starts a dump, the list of refptrs is copied into the -// ProcessMemoryDumpAsyncState. That list is pruned as MDP(s) are invoked. -// - If UnregisterDumpProvider() is called on a non-thread-bound MDP while a -// dump is in progress, the extar extra of the handle is destroyed in -// MDM::SetupNextMemoryDump() or MDM::InvokeOnMemoryDump(), when the copy -// inside ProcessMemoryDumpAsyncState is erase()-d. -// - The PeakDetector can keep extra refptrs when enabled. -struct BASE_EXPORT MemoryDumpProviderInfo - : public RefCountedThreadSafe<MemoryDumpProviderInfo> { - public: - // Define a total order based on the |task_runner| affinity, so that MDPs - // belonging to the same SequencedTaskRunner are adjacent in the set. - struct Comparator { - bool operator()(const scoped_refptr<MemoryDumpProviderInfo>& a, - const scoped_refptr<MemoryDumpProviderInfo>& b) const; - }; - using OrderedSet = - std::set<scoped_refptr<MemoryDumpProviderInfo>, Comparator>; - - MemoryDumpProviderInfo(MemoryDumpProvider* dump_provider, - const char* name, - scoped_refptr<SequencedTaskRunner> task_runner, - const MemoryDumpProvider::Options& options, - bool whitelisted_for_background_mode); - - // It is safe to access the const fields below from any thread as they are - // never mutated. - - MemoryDumpProvider* const dump_provider; - - // The |options| arg passed to MDM::RegisterDumpProvider(). - const MemoryDumpProvider::Options options; - - // Human readable name, not unique (distinct MDP instances might have the same - // name). Used for debugging, testing and whitelisting for BACKGROUND mode. - const char* const name; - - // The task runner on which the MDP::OnMemoryDump call should be posted onto. - // Can be nullptr, in which case the MDP will be invoked on a background - // thread handled by MDM. - const scoped_refptr<SequencedTaskRunner> task_runner; - - // True if the dump provider is whitelisted for background mode. - const bool whitelisted_for_background_mode; - - // These fields below, instead, are not thread safe and can be mutated only: - // - On the |task_runner|, when not null (i.e. for thread-bound MDPS). - // - By the MDM's background thread (or in any other way that guarantees - // sequencing) for non-thread-bound MDPs. - - // Used to transfer ownership for UnregisterAndDeleteDumpProviderSoon(). - // nullptr in all other cases. - std::unique_ptr<MemoryDumpProvider> owned_dump_provider; - - // For fail-safe logic (auto-disable failing MDPs). - int consecutive_failures; - - // Flagged either by the auto-disable logic or during unregistration. - bool disabled; - - private: - friend class base::RefCountedThreadSafe<MemoryDumpProviderInfo>; - ~MemoryDumpProviderInfo(); - - DISALLOW_COPY_AND_ASSIGN(MemoryDumpProviderInfo); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_INFO_H_
diff --git a/base/trace_event/memory_dump_request_args.cc b/base/trace_event/memory_dump_request_args.cc deleted file mode 100644 index 3cb9cab..0000000 --- a/base/trace_event/memory_dump_request_args.cc +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_dump_request_args.h" - -#include "base/logging.h" - -namespace base { -namespace trace_event { - -// static -const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) { - switch (dump_type) { - case MemoryDumpType::PERIODIC_INTERVAL: - return "periodic_interval"; - case MemoryDumpType::EXPLICITLY_TRIGGERED: - return "explicitly_triggered"; - case MemoryDumpType::PEAK_MEMORY_USAGE: - return "peak_memory_usage"; - case MemoryDumpType::SUMMARY_ONLY: - return "summary_only"; - } - NOTREACHED(); - return "unknown"; -} - -MemoryDumpType StringToMemoryDumpType(const std::string& str) { - if (str == "periodic_interval") - return MemoryDumpType::PERIODIC_INTERVAL; - if (str == "explicitly_triggered") - return MemoryDumpType::EXPLICITLY_TRIGGERED; - if (str == "peak_memory_usage") - return MemoryDumpType::PEAK_MEMORY_USAGE; - if (str == "summary_only") - return MemoryDumpType::SUMMARY_ONLY; - NOTREACHED(); - return MemoryDumpType::LAST; -} - -const char* MemoryDumpLevelOfDetailToString( - const MemoryDumpLevelOfDetail& level_of_detail) { - switch (level_of_detail) { - case MemoryDumpLevelOfDetail::BACKGROUND: - return "background"; - case MemoryDumpLevelOfDetail::LIGHT: - return "light"; - case MemoryDumpLevelOfDetail::DETAILED: - return "detailed"; - } - NOTREACHED(); - return "unknown"; -} - -MemoryDumpLevelOfDetail StringToMemoryDumpLevelOfDetail( - const std::string& str) { - if (str == "background") - return MemoryDumpLevelOfDetail::BACKGROUND; - if (str == "light") - return MemoryDumpLevelOfDetail::LIGHT; - if (str == "detailed") - return MemoryDumpLevelOfDetail::DETAILED; - NOTREACHED(); - return MemoryDumpLevelOfDetail::LAST; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_dump_request_args.h b/base/trace_event/memory_dump_request_args.h deleted file mode 100644 index 41bc99b..0000000 --- a/base/trace_event/memory_dump_request_args.h +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_ARGS_H_ -#define BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_ARGS_H_ - -// This file defines the types and structs used to issue memory dump requests. -// These are also used in the IPCs for coordinating inter-process memory dumps. - -#include <stdint.h> -#include <map> -#include <memory> -#include <string> - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/optional.h" -#include "base/process/process_handle.h" - -namespace base { -namespace trace_event { - -class ProcessMemoryDump; - -// Captures the reason why a memory dump is being requested. This is to allow -// selective enabling of dumps, filtering and post-processing. Keep this -// consistent with memory_instrumentation.mojo and -// memory_instrumentation_struct_traits.{h,cc} -enum class MemoryDumpType { - PERIODIC_INTERVAL, // Dumping memory at periodic intervals. - EXPLICITLY_TRIGGERED, // Non maskable dump request. - PEAK_MEMORY_USAGE, // Dumping memory at detected peak total memory usage. - SUMMARY_ONLY, // Calculate just the summary & don't add to the trace. - LAST = SUMMARY_ONLY -}; - -// Tells the MemoryDumpProvider(s) how much detailed their dumps should be. -// Keep this consistent with memory_instrumentation.mojo and -// memory_instrumentation_struct_traits.{h,cc} -enum class MemoryDumpLevelOfDetail : uint32_t { - FIRST, - - // For background tracing mode. The dump time is quick, and typically just the - // totals are expected. Suballocations need not be specified. Dump name must - // contain only pre-defined strings and string arguments cannot be added. - BACKGROUND = FIRST, - - // For the levels below, MemoryDumpProvider instances must guarantee that the - // total size reported in the root node is consistent. Only the granularity of - // the child MemoryAllocatorDump(s) differs with the levels. - - // Few entries, typically a fixed number, per dump. - LIGHT, - - // Unrestricted amount of entries per dump. - DETAILED, - - LAST = DETAILED -}; - -// Keep this consistent with memory_instrumentation.mojo and -// memory_instrumentation_struct_traits.{h,cc} -struct BASE_EXPORT MemoryDumpRequestArgs { - // Globally unique identifier. In multi-process dumps, all processes issue a - // local dump with the same guid. This allows the trace importers to - // reconstruct the global dump. - uint64_t dump_guid; - - MemoryDumpType dump_type; - MemoryDumpLevelOfDetail level_of_detail; -}; - -// Args for ProcessMemoryDump and passed to OnMemoryDump calls for memory dump -// providers. Dump providers are expected to read the args for creating dumps. -struct MemoryDumpArgs { - // Specifies how detailed the dumps should be. - MemoryDumpLevelOfDetail level_of_detail; - - // Globally unique identifier. In multi-process dumps, all processes issue a - // local dump with the same guid. This allows the trace importers to - // reconstruct the global dump. - uint64_t dump_guid; -}; - -using ProcessMemoryDumpCallback = Callback< - void(bool success, uint64_t dump_guid, std::unique_ptr<ProcessMemoryDump>)>; - -BASE_EXPORT const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type); - -BASE_EXPORT MemoryDumpType StringToMemoryDumpType(const std::string& str); - -BASE_EXPORT const char* MemoryDumpLevelOfDetailToString( - const MemoryDumpLevelOfDetail& level_of_detail); - -BASE_EXPORT MemoryDumpLevelOfDetail -StringToMemoryDumpLevelOfDetail(const std::string& str); - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_ARGS_H_
diff --git a/base/trace_event/memory_dump_scheduler.cc b/base/trace_event/memory_dump_scheduler.cc deleted file mode 100644 index 8b03f5c..0000000 --- a/base/trace_event/memory_dump_scheduler.cc +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_dump_scheduler.h" - -#include <algorithm> -#include <limits> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/threading/sequenced_task_runner_handle.h" - -namespace base { -namespace trace_event { - -// static -MemoryDumpScheduler* MemoryDumpScheduler::GetInstance() { - static MemoryDumpScheduler* instance = new MemoryDumpScheduler(); - return instance; -} - -MemoryDumpScheduler::MemoryDumpScheduler() : period_ms_(0), generation_(0) {} -MemoryDumpScheduler::~MemoryDumpScheduler() { - // Hit only in tests. Check that tests don't leave without stopping. - DCHECK(!is_enabled_for_testing()); -} - -void MemoryDumpScheduler::Start( - MemoryDumpScheduler::Config config, - scoped_refptr<SequencedTaskRunner> task_runner) { - DCHECK(!task_runner_); - task_runner_ = task_runner; - task_runner->PostTask(FROM_HERE, BindOnce(&MemoryDumpScheduler::StartInternal, - Unretained(this), config)); -} - -void MemoryDumpScheduler::Stop() { - if (!task_runner_) - return; - task_runner_->PostTask(FROM_HERE, BindOnce(&MemoryDumpScheduler::StopInternal, - Unretained(this))); - task_runner_ = nullptr; -} - -void MemoryDumpScheduler::StartInternal(MemoryDumpScheduler::Config config) { - uint32_t light_dump_period_ms = 0; - uint32_t heavy_dump_period_ms = 0; - uint32_t min_period_ms = std::numeric_limits<uint32_t>::max(); - for (const Config::Trigger& trigger : config.triggers) { - DCHECK_GT(trigger.period_ms, 0u); - switch (trigger.level_of_detail) { - case MemoryDumpLevelOfDetail::BACKGROUND: - break; - case MemoryDumpLevelOfDetail::LIGHT: - DCHECK_EQ(0u, light_dump_period_ms); - light_dump_period_ms = trigger.period_ms; - break; - case MemoryDumpLevelOfDetail::DETAILED: - DCHECK_EQ(0u, heavy_dump_period_ms); - heavy_dump_period_ms = trigger.period_ms; - break; - } - min_period_ms = std::min(min_period_ms, trigger.period_ms); - } - - DCHECK_EQ(0u, light_dump_period_ms % min_period_ms); - DCHECK_EQ(0u, heavy_dump_period_ms % min_period_ms); - DCHECK(!config.callback.is_null()); - callback_ = config.callback; - period_ms_ = min_period_ms; - tick_count_ = 0; - light_dump_rate_ = light_dump_period_ms / min_period_ms; - heavy_dump_rate_ = heavy_dump_period_ms / min_period_ms; - - // Trigger the first dump after 200ms. - // TODO(lalitm): this is a tempoarary hack to delay the first scheduled dump - // so that the child processes get tracing enabled notification via IPC. - // See crbug.com/770151. - SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - BindOnce(&MemoryDumpScheduler::Tick, Unretained(this), ++generation_), - TimeDelta::FromMilliseconds(200)); -} - -void MemoryDumpScheduler::StopInternal() { - period_ms_ = 0; - generation_++; - callback_.Reset(); -} - -void MemoryDumpScheduler::Tick(uint32_t expected_generation) { - if (period_ms_ == 0 || generation_ != expected_generation) - return; - - MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; - if (light_dump_rate_ > 0 && tick_count_ % light_dump_rate_ == 0) - level_of_detail = MemoryDumpLevelOfDetail::LIGHT; - if (heavy_dump_rate_ > 0 && tick_count_ % heavy_dump_rate_ == 0) - level_of_detail = MemoryDumpLevelOfDetail::DETAILED; - tick_count_++; - - callback_.Run(level_of_detail); - - SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - BindOnce(&MemoryDumpScheduler::Tick, Unretained(this), - expected_generation), - TimeDelta::FromMilliseconds(period_ms_)); -} - -MemoryDumpScheduler::Config::Config() = default; -MemoryDumpScheduler::Config::~Config() = default; -MemoryDumpScheduler::Config::Config(const MemoryDumpScheduler::Config&) = - default; - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_dump_scheduler.h b/base/trace_event/memory_dump_scheduler.h deleted file mode 100644 index 21334f0..0000000 --- a/base/trace_event/memory_dump_scheduler.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H -#define BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H - -#include <stdint.h> - -#include <vector> - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "base/trace_event/memory_dump_request_args.h" - -namespace base { -class SequencedTaskRunner; - -namespace trace_event { - -// Schedules global dump requests based on the triggers added. The methods of -// this class are NOT thread safe and the client has to take care of invoking -// all the methods of the class safely. -class BASE_EXPORT MemoryDumpScheduler { - public: - using PeriodicCallback = RepeatingCallback<void(MemoryDumpLevelOfDetail)>; - - // Passed to Start(). - struct BASE_EXPORT Config { - struct Trigger { - MemoryDumpLevelOfDetail level_of_detail; - uint32_t period_ms; - }; - - Config(); - Config(const Config&); - ~Config(); - - std::vector<Trigger> triggers; - PeriodicCallback callback; - }; - - static MemoryDumpScheduler* GetInstance(); - - void Start(Config, scoped_refptr<SequencedTaskRunner> task_runner); - void Stop(); - bool is_enabled_for_testing() const { return bool(task_runner_); } - - private: - friend class MemoryDumpSchedulerTest; - MemoryDumpScheduler(); - ~MemoryDumpScheduler(); - - void StartInternal(Config); - void StopInternal(); - void Tick(uint32_t expected_generation); - - // Accessed only by the public methods (never from the task runner itself). - scoped_refptr<SequencedTaskRunner> task_runner_; - - // These fields instead are only accessed from within the task runner. - uint32_t period_ms_; // 0 == disabled. - uint32_t generation_; // Used to invalidate outstanding tasks after Stop(). - uint32_t tick_count_; - uint32_t light_dump_rate_; - uint32_t heavy_dump_rate_; - PeriodicCallback callback_; - - DISALLOW_COPY_AND_ASSIGN(MemoryDumpScheduler); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc deleted file mode 100644 index 0e69c7c..0000000 --- a/base/trace_event/memory_infra_background_whitelist.cc +++ /dev/null
@@ -1,386 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_infra_background_whitelist.h" - -#include <ctype.h> -#include <string.h> - -#include <string> - -#include "base/strings/string_util.h" - -namespace base { -namespace trace_event { -namespace { - -// The names of dump providers whitelisted for background tracing. Dump -// providers can be added here only if the background mode dump has very -// little processor and memory overhead. -// TODO(ssid): Some dump providers do not create ownership edges on background -// dump. So, the effective size will not be correct. -const char* const kDumpProviderWhitelist[] = { - "android::ResourceManagerImpl", - "AutocompleteController", - "BlinkGC", - "BlinkObjectCounters", - "BlobStorageContext", - "ClientDiscardableSharedMemoryManager", - "DOMStorage", - "DownloadService", - "DiscardableSharedMemoryManager", - "gpu::BufferManager", - "gpu::RenderbufferManager", - "gpu::TextureManager", - "FontCaches", - "HistoryReport", - "IPCChannel", - "IndexedDBBackingStore", - "InMemoryURLIndex", - "JavaHeap", - "LevelDB", - "LeveldbValueStore", - "LocalStorage", - "Malloc", - "MemoryCache", - "MojoHandleTable", - "MojoLevelDB", - "MojoMessages", - "PartitionAlloc", - "ProcessMemoryMetrics", - "RenderProcessHost", - "SharedMemoryTracker", - "Skia", - "Sql", - "URLRequestContext", - "V8Isolate", - "SyncDirectory", - "TabRestoreServiceHelper", - nullptr // End of list marker. -}; - -// A list of string names that are allowed for the memory allocator dumps in -// background mode. -const char* const kAllocatorDumpNameWhitelist[] = { - "blink_gc", - "blink_gc/allocated_objects", - "blink_objects/AudioHandler", - "blink_objects/Document", - "blink_objects/Frame", - "blink_objects/JSEventListener", - "blink_objects/LayoutObject", - "blink_objects/MediaKeySession", - "blink_objects/MediaKeys", - "blink_objects/Node", - "blink_objects/Resource", - "blink_objects/RTCPeerConnection", - "blink_objects/ScriptPromise", - "blink_objects/PausableObject", - "blink_objects/V8PerContextData", - "blink_objects/WorkerGlobalScope", - "blink_objects/UACSSResource", - "blink_objects/ResourceFetcher", - "components/download/controller_0x?", - "discardable", - "discardable/child_0x?", - "extensions/value_store/Extensions.Database.Open.Settings/0x?", - "extensions/value_store/Extensions.Database.Open.Rules/0x?", - "extensions/value_store/Extensions.Database.Open.State/0x?", - "extensions/value_store/Extensions.Database.Open/0x?", - "extensions/value_store/Extensions.Database.Restore/0x?", - "extensions/value_store/Extensions.Database.Value.Restore/0x?", - "font_caches/font_platform_data_cache", - "font_caches/shape_caches", - "gpu/gl/buffers/share_group_0x?", - "gpu/gl/renderbuffers/share_group_0x?", - "gpu/gl/textures/share_group_0x?", - "history/delta_file_service/leveldb_0x?", - "history/usage_reports_buffer/leveldb_0x?", - "java_heap", - "java_heap/allocated_objects", - "leveldatabase", - "leveldatabase/block_cache/browser", - "leveldatabase/block_cache/in_memory", - "leveldatabase/block_cache/unified", - "leveldatabase/block_cache/web", - "leveldatabase/db_0x?", - "leveldatabase/db_0x?/block_cache", - "leveldatabase/memenv_0x?", - "malloc", - "malloc/allocated_objects", - "malloc/metadata_fragmentation_caches", - "mojo", - "mojo/data_pipe_consumer", - "mojo/data_pipe_producer", - "mojo/messages", - "mojo/message_pipe", - "mojo/platform_handle", - "mojo/queued_ipc_channel_message/0x?", - "mojo/render_process_host/0x?", - "mojo/shared_buffer", - "mojo/unknown", - "mojo/watcher", - "net/http_network_session_0x?", - "net/http_network_session_0x?/quic_stream_factory", - "net/http_network_session_0x?/socket_pool", - "net/http_network_session_0x?/spdy_session_pool", - "net/http_network_session_0x?/stream_factory", - "net/ssl_session_cache", - "net/url_request_context", - "net/url_request_context/app_request", - "net/url_request_context/app_request/0x?", - "net/url_request_context/app_request/0x?/cookie_monster", - "net/url_request_context/app_request/0x?/cookie_monster/cookies", - "net/url_request_context/app_request/0x?/cookie_monster/" - "tasks_pending_global", - "net/url_request_context/app_request/0x?/cookie_monster/" - "tasks_pending_for_key", - "net/url_request_context/app_request/0x?/http_cache", - "net/url_request_context/app_request/0x?/http_cache/memory_backend", - "net/url_request_context/app_request/0x?/http_cache/simple_backend", - "net/url_request_context/app_request/0x?/http_network_session", - "net/url_request_context/extensions", - "net/url_request_context/extensions/0x?", - "net/url_request_context/extensions/0x?/cookie_monster", - "net/url_request_context/extensions/0x?/cookie_monster/cookies", - "net/url_request_context/extensions/0x?/cookie_monster/" - "tasks_pending_global", - "net/url_request_context/extensions/0x?/cookie_monster/" - "tasks_pending_for_key", - "net/url_request_context/extensions/0x?/http_cache", - "net/url_request_context/extensions/0x?/http_cache/memory_backend", - "net/url_request_context/extensions/0x?/http_cache/simple_backend", - "net/url_request_context/extensions/0x?/http_network_session", - "net/url_request_context/isolated_media", - "net/url_request_context/isolated_media/0x?", - "net/url_request_context/isolated_media/0x?/cookie_monster", - "net/url_request_context/isolated_media/0x?/cookie_monster/cookies", - "net/url_request_context/isolated_media/0x?/cookie_monster/" - "tasks_pending_global", - "net/url_request_context/isolated_media/0x?/cookie_monster/" - "tasks_pending_for_key", - "net/url_request_context/isolated_media/0x?/http_cache", - "net/url_request_context/isolated_media/0x?/http_cache/memory_backend", - "net/url_request_context/isolated_media/0x?/http_cache/simple_backend", - "net/url_request_context/isolated_media/0x?/http_network_session", - "net/url_request_context/main", - "net/url_request_context/main/0x?", - "net/url_request_context/main/0x?/cookie_monster", - "net/url_request_context/main/0x?/cookie_monster/cookies", - "net/url_request_context/main/0x?/cookie_monster/tasks_pending_global", - "net/url_request_context/main/0x?/cookie_monster/tasks_pending_for_key", - "net/url_request_context/main/0x?/http_cache", - "net/url_request_context/main/0x?/http_cache/memory_backend", - "net/url_request_context/main/0x?/http_cache/simple_backend", - "net/url_request_context/main/0x?/http_network_session", - "net/url_request_context/main_media", - "net/url_request_context/main_media/0x?", - "net/url_request_context/main_media/0x?/cookie_monster", - "net/url_request_context/main_media/0x?/cookie_monster/cookies", - "net/url_request_context/main_media/0x?/cookie_monster/" - "tasks_pending_global", - "net/url_request_context/main_media/0x?/cookie_monster/" - "tasks_pending_for_key", - "net/url_request_context/main_media/0x?/http_cache", - "net/url_request_context/main_media/0x?/http_cache/memory_backend", - "net/url_request_context/main_media/0x?/http_cache/simple_backend", - "net/url_request_context/main_media/0x?/http_network_session", - "net/url_request_context/proxy", - "net/url_request_context/proxy/0x?", - "net/url_request_context/proxy/0x?/cookie_monster", - "net/url_request_context/proxy/0x?/cookie_monster/cookies", - "net/url_request_context/proxy/0x?/cookie_monster/tasks_pending_global", - "net/url_request_context/proxy/0x?/cookie_monster/tasks_pending_for_key", - "net/url_request_context/proxy/0x?/http_cache", - "net/url_request_context/proxy/0x?/http_cache/memory_backend", - "net/url_request_context/proxy/0x?/http_cache/simple_backend", - "net/url_request_context/proxy/0x?/http_network_session", - "net/url_request_context/safe_browsing", - "net/url_request_context/safe_browsing/0x?", - "net/url_request_context/safe_browsing/0x?/cookie_monster", - "net/url_request_context/safe_browsing/0x?/cookie_monster/cookies", - "net/url_request_context/safe_browsing/0x?/cookie_monster/" - "tasks_pending_global", - "net/url_request_context/safe_browsing/0x?/cookie_monster/" - "tasks_pending_for_key", - "net/url_request_context/safe_browsing/0x?/http_cache", - "net/url_request_context/safe_browsing/0x?/http_cache/memory_backend", - "net/url_request_context/safe_browsing/0x?/http_cache/simple_backend", - "net/url_request_context/safe_browsing/0x?/http_network_session", - "net/url_request_context/system", - "net/url_request_context/system/0x?", - "net/url_request_context/system/0x?/cookie_monster", - "net/url_request_context/system/0x?/cookie_monster/cookies", - "net/url_request_context/system/0x?/cookie_monster/tasks_pending_global", - "net/url_request_context/system/0x?/cookie_monster/tasks_pending_for_key", - "net/url_request_context/system/0x?/http_cache", - "net/url_request_context/system/0x?/http_cache/memory_backend", - "net/url_request_context/system/0x?/http_cache/simple_backend", - "net/url_request_context/system/0x?/http_network_session", - "net/url_request_context/unknown", - "net/url_request_context/unknown/0x?", - "net/url_request_context/unknown/0x?/cookie_monster", - "net/url_request_context/unknown/0x?/cookie_monster/cookies", - "net/url_request_context/unknown/0x?/cookie_monster/tasks_pending_global", - "net/url_request_context/unknown/0x?/cookie_monster/tasks_pending_for_key", - "net/url_request_context/unknown/0x?/http_cache", - "net/url_request_context/unknown/0x?/http_cache/memory_backend", - "net/url_request_context/unknown/0x?/http_cache/simple_backend", - "net/url_request_context/unknown/0x?/http_network_session", - "omnibox/autocomplete_controller/0x?", - "omnibox/in_memory_url_index/0x?", - "web_cache/Image_resources", - "web_cache/CSS stylesheet_resources", - "web_cache/Script_resources", - "web_cache/XSL stylesheet_resources", - "web_cache/Font_resources", - "web_cache/Other_resources", - "partition_alloc/allocated_objects", - "partition_alloc/partitions", - "partition_alloc/partitions/array_buffer", - "partition_alloc/partitions/buffer", - "partition_alloc/partitions/fast_malloc", - "partition_alloc/partitions/layout", - "skia/sk_glyph_cache", - "skia/sk_resource_cache", - "sqlite", - "ui/resource_manager_0x?/default_resource/0x?", - "ui/resource_manager_0x?/tinted_resource", - "v8/isolate_0x?/contexts/detached_context", - "v8/isolate_0x?/contexts/native_context", - "v8/isolate_0x?/heap_spaces", - "v8/isolate_0x?/heap_spaces/code_space", - "v8/isolate_0x?/heap_spaces/large_object_space", - "v8/isolate_0x?/heap_spaces/map_space", - "v8/isolate_0x?/heap_spaces/new_space", - "v8/isolate_0x?/heap_spaces/old_space", - "v8/isolate_0x?/heap_spaces/read_only_space", - "v8/isolate_0x?/malloc", - "v8/isolate_0x?/zapped_for_debug", - "site_storage/blob_storage/0x?", - "site_storage/index_db/db_0x?", - "site_storage/index_db/memenv_0x?", - "site_storage/localstorage/0x?/cache_size", - "site_storage/localstorage/0x?/leveldb", - "site_storage/session_storage/0x?", - "site_storage/session_storage/0x?/cache_size", - "sync/0x?/kernel", - "sync/0x?/store", - "sync/0x?/model_type/APP", - "sync/0x?/model_type/APP_LIST", - "sync/0x?/model_type/APP_NOTIFICATION", - "sync/0x?/model_type/APP_SETTING", - "sync/0x?/model_type/ARC_PACKAGE", - "sync/0x?/model_type/ARTICLE", - "sync/0x?/model_type/AUTOFILL", - "sync/0x?/model_type/AUTOFILL_PROFILE", - "sync/0x?/model_type/AUTOFILL_WALLET", - "sync/0x?/model_type/BOOKMARK", - "sync/0x?/model_type/DEVICE_INFO", - "sync/0x?/model_type/DICTIONARY", - "sync/0x?/model_type/EXPERIMENTS", - "sync/0x?/model_type/EXTENSION", - "sync/0x?/model_type/EXTENSION_SETTING", - "sync/0x?/model_type/FAVICON_IMAGE", - "sync/0x?/model_type/FAVICON_TRACKING", - "sync/0x?/model_type/HISTORY_DELETE_DIRECTIVE", - "sync/0x?/model_type/MANAGED_USER", - "sync/0x?/model_type/MANAGED_USER_SETTING", - "sync/0x?/model_type/MANAGED_USER_SHARED_SETTING", - "sync/0x?/model_type/MANAGED_USER_WHITELIST", - "sync/0x?/model_type/NIGORI", - "sync/0x?/model_type/PASSWORD", - "sync/0x?/model_type/PREFERENCE", - "sync/0x?/model_type/PRINTER", - "sync/0x?/model_type/PRIORITY_PREFERENCE", - "sync/0x?/model_type/READING_LIST", - "sync/0x?/model_type/SEARCH_ENGINE", - "sync/0x?/model_type/SESSION", - "sync/0x?/model_type/SYNCED_NOTIFICATION", - "sync/0x?/model_type/SYNCED_NOTIFICATION_APP_INFO", - "sync/0x?/model_type/THEME", - "sync/0x?/model_type/TYPED_URL", - "sync/0x?/model_type/USER_EVENT", - "sync/0x?/model_type/WALLET_METADATA", - "sync/0x?/model_type/WIFI_CREDENTIAL", - "tab_restore/service_helper_0x?/entries", - "tab_restore/service_helper_0x?/entries/tab_0x?", - "tab_restore/service_helper_0x?/entries/window_0x?", - "tracing/heap_profiler_blink_gc/AllocationRegister", - "tracing/heap_profiler_malloc/AllocationRegister", - "tracing/heap_profiler_partition_alloc/AllocationRegister", - nullptr // End of list marker. -}; - -const char* const* g_dump_provider_whitelist = kDumpProviderWhitelist; -const char* const* g_allocator_dump_name_whitelist = - kAllocatorDumpNameWhitelist; - -bool IsMemoryDumpProviderInList(const char* mdp_name, const char* const* list) { - for (size_t i = 0; list[i] != nullptr; ++i) { - if (strcmp(mdp_name, list[i]) == 0) - return true; - } - return false; -} - -} // namespace - -bool IsMemoryDumpProviderWhitelisted(const char* mdp_name) { - return IsMemoryDumpProviderInList(mdp_name, g_dump_provider_whitelist); -} - -bool IsMemoryAllocatorDumpNameWhitelisted(const std::string& name) { - // Global dumps are explicitly whitelisted for background use. - if (base::StartsWith(name, "global/", CompareCase::SENSITIVE)) { - for (size_t i = strlen("global/"); i < name.size(); i++) - if (!base::IsHexDigit(name[i])) - return false; - return true; - } - - if (base::StartsWith(name, "shared_memory/", CompareCase::SENSITIVE)) { - for (size_t i = strlen("shared_memory/"); i < name.size(); i++) - if (!base::IsHexDigit(name[i])) - return false; - return true; - } - - // Remove special characters, numbers (including hexadecimal which are marked - // by '0x') from the given string. - const size_t length = name.size(); - std::string stripped_str; - stripped_str.reserve(length); - bool parsing_hex = false; - for (size_t i = 0; i < length; ++i) { - if (parsing_hex && isxdigit(name[i])) - continue; - parsing_hex = false; - if (i + 1 < length && name[i] == '0' && name[i + 1] == 'x') { - parsing_hex = true; - stripped_str.append("0x?"); - ++i; - } else { - stripped_str.push_back(name[i]); - } - } - - for (size_t i = 0; g_allocator_dump_name_whitelist[i] != nullptr; ++i) { - if (stripped_str == g_allocator_dump_name_whitelist[i]) { - return true; - } - } - return false; -} - -void SetDumpProviderWhitelistForTesting(const char* const* list) { - g_dump_provider_whitelist = list; -} - -void SetAllocatorDumpNameWhitelistForTesting(const char* const* list) { - g_allocator_dump_name_whitelist = list; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_infra_background_whitelist.h b/base/trace_event/memory_infra_background_whitelist.h deleted file mode 100644 index b8d704a..0000000 --- a/base/trace_event/memory_infra_background_whitelist.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_ -#define BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_ - -// This file contains the whitelists for background mode to limit the tracing -// overhead and remove sensitive information from traces. - -#include <string> - -#include "base/base_export.h" - -namespace base { -namespace trace_event { - -// Checks if the given |mdp_name| is in the whitelist. -bool BASE_EXPORT IsMemoryDumpProviderWhitelisted(const char* mdp_name); - -// Checks if the given |name| matches any of the whitelisted patterns. -bool BASE_EXPORT IsMemoryAllocatorDumpNameWhitelisted(const std::string& name); - -// The whitelist is replaced with the given list for tests. The last element of -// the list must be nullptr. -void BASE_EXPORT SetDumpProviderWhitelistForTesting(const char* const* list); -void BASE_EXPORT -SetAllocatorDumpNameWhitelistForTesting(const char* const* list); - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_
diff --git a/base/trace_event/memory_peak_detector.cc b/base/trace_event/memory_peak_detector.cc deleted file mode 100644 index 5f2ea91..0000000 --- a/base/trace_event/memory_peak_detector.cc +++ /dev/null
@@ -1,288 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_peak_detector.h" - -#include <algorithm> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/sys_info.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "base/time/time.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/memory_dump_provider_info.h" -#include "base/trace_event/trace_event.h" -#include "build_config.h" - -namespace base { -namespace trace_event { - -// static -MemoryPeakDetector* MemoryPeakDetector::GetInstance() { - static MemoryPeakDetector* instance = new MemoryPeakDetector(); - return instance; -} - -MemoryPeakDetector::MemoryPeakDetector() - : generation_(0), - state_(NOT_INITIALIZED), - poll_tasks_count_for_testing_(0) {} - -MemoryPeakDetector::~MemoryPeakDetector() { - // This is hit only in tests, in which case the test is expected to TearDown() - // cleanly and not leave the peak detector running. - DCHECK_EQ(NOT_INITIALIZED, state_); -} - -void MemoryPeakDetector::Setup( - const GetDumpProvidersFunction& get_dump_providers_function, - const scoped_refptr<SequencedTaskRunner>& task_runner, - const OnPeakDetectedCallback& on_peak_detected_callback) { - DCHECK(!get_dump_providers_function.is_null()); - DCHECK(task_runner); - DCHECK(!on_peak_detected_callback.is_null()); - DCHECK(state_ == NOT_INITIALIZED || state_ == DISABLED); - DCHECK(dump_providers_.empty()); - get_dump_providers_function_ = get_dump_providers_function; - task_runner_ = task_runner; - on_peak_detected_callback_ = on_peak_detected_callback; - state_ = DISABLED; - config_ = {}; - ResetPollHistory(); - - static_threshold_bytes_ = 0; -#if !defined(OS_NACL) - // Set threshold to 1% of total system memory. - static_threshold_bytes_ = - static_cast<uint64_t>(SysInfo::AmountOfPhysicalMemory()) / 100; -#endif - // Fallback, mostly for test environments where AmountOfPhysicalMemory() is - // broken. - static_threshold_bytes_ = - std::max(static_threshold_bytes_, static_cast<uint64_t>(5 * 1024 * 1024)); -} - -void MemoryPeakDetector::TearDown() { - if (task_runner_) { - task_runner_->PostTask( - FROM_HERE, - BindOnce(&MemoryPeakDetector::TearDownInternal, Unretained(this))); - } - task_runner_ = nullptr; -} - -void MemoryPeakDetector::Start(MemoryPeakDetector::Config config) { - if (!config.polling_interval_ms) { - NOTREACHED(); - return; - } - task_runner_->PostTask(FROM_HERE, BindOnce(&MemoryPeakDetector::StartInternal, - Unretained(this), config)); -} - -void MemoryPeakDetector::Stop() { - task_runner_->PostTask( - FROM_HERE, BindOnce(&MemoryPeakDetector::StopInternal, Unretained(this))); -} - -void MemoryPeakDetector::Throttle() { - if (!task_runner_) - return; // Can be called before Setup(). - task_runner_->PostTask( - FROM_HERE, BindOnce(&MemoryPeakDetector::ResetPollHistory, - Unretained(this), true /* keep_last_sample */)); -} - -void MemoryPeakDetector::NotifyMemoryDumpProvidersChanged() { - if (!task_runner_) - return; // Can be called before Setup(). - task_runner_->PostTask( - FROM_HERE, - BindOnce(&MemoryPeakDetector::ReloadDumpProvidersAndStartPollingIfNeeded, - Unretained(this))); -} - -void MemoryPeakDetector::StartInternal(MemoryPeakDetector::Config config) { - DCHECK_EQ(DISABLED, state_); - state_ = ENABLED; - config_ = config; - ResetPollHistory(); - - // If there are any dump providers available, - // NotifyMemoryDumpProvidersChanged will fetch them and start the polling. - // Otherwise this will remain in the ENABLED state and the actual polling - // will start on the next call to - // ReloadDumpProvidersAndStartPollingIfNeeded(). - // Depending on the sandbox model, it is possible that no polling-capable - // dump providers will be ever available. - ReloadDumpProvidersAndStartPollingIfNeeded(); -} - -void MemoryPeakDetector::StopInternal() { - DCHECK_NE(NOT_INITIALIZED, state_); - state_ = DISABLED; - ++generation_; - for (const scoped_refptr<MemoryDumpProviderInfo>& mdp_info : dump_providers_) - mdp_info->dump_provider->SuspendFastMemoryPolling(); - dump_providers_.clear(); -} - -void MemoryPeakDetector::TearDownInternal() { - StopInternal(); - get_dump_providers_function_.Reset(); - on_peak_detected_callback_.Reset(); - state_ = NOT_INITIALIZED; -} - -void MemoryPeakDetector::ReloadDumpProvidersAndStartPollingIfNeeded() { - if (state_ == DISABLED || state_ == NOT_INITIALIZED) - return; // Start() will re-fetch the MDP list later. - - DCHECK((state_ == RUNNING && !dump_providers_.empty()) || - (state_ == ENABLED && dump_providers_.empty())); - - dump_providers_.clear(); - - // This is really MemoryDumpManager::GetDumpProvidersForPolling, % testing. - get_dump_providers_function_.Run(&dump_providers_); - - if (state_ == ENABLED && !dump_providers_.empty()) { - // It's now time to start polling for realz. - state_ = RUNNING; - task_runner_->PostTask( - FROM_HERE, BindOnce(&MemoryPeakDetector::PollMemoryAndDetectPeak, - Unretained(this), ++generation_)); - } else if (state_ == RUNNING && dump_providers_.empty()) { - // Will cause the next PollMemoryAndDetectPeak() task to early return. - state_ = ENABLED; - ++generation_; - } -} - -void MemoryPeakDetector::PollMemoryAndDetectPeak(uint32_t expected_generation) { - if (state_ != RUNNING || generation_ != expected_generation) - return; - - // We should never end up in a situation where state_ == RUNNING but all dump - // providers are gone. - DCHECK(!dump_providers_.empty()); - - poll_tasks_count_for_testing_++; - uint64_t polled_mem_bytes = 0; - for (const scoped_refptr<MemoryDumpProviderInfo>& mdp_info : - dump_providers_) { - DCHECK(mdp_info->options.is_fast_polling_supported); - uint64_t value = 0; - mdp_info->dump_provider->PollFastMemoryTotal(&value); - polled_mem_bytes += value; - } - if (config_.enable_verbose_poll_tracing) { - TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", - polled_mem_bytes / 1024 / 1024); - } - - // Peak detection logic. Design doc: https://goo.gl/0kOU4A . - bool is_peak = false; - if (skip_polls_ > 0) { - skip_polls_--; - } else if (last_dump_memory_total_ == 0) { - last_dump_memory_total_ = polled_mem_bytes; - } else if (polled_mem_bytes > 0) { - int64_t diff_from_last_dump = polled_mem_bytes - last_dump_memory_total_; - - DCHECK_GT(static_threshold_bytes_, 0u); - is_peak = - diff_from_last_dump > static_cast<int64_t>(static_threshold_bytes_); - - if (!is_peak) - is_peak = DetectPeakUsingSlidingWindowStddev(polled_mem_bytes); - } - - DCHECK_GT(config_.polling_interval_ms, 0u); - SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - BindOnce(&MemoryPeakDetector::PollMemoryAndDetectPeak, Unretained(this), - expected_generation), - TimeDelta::FromMilliseconds(config_.polling_interval_ms)); - - if (!is_peak) - return; - TRACE_EVENT_INSTANT1(MemoryDumpManager::kTraceCategory, - "Peak memory detected", TRACE_EVENT_SCOPE_PROCESS, - "PolledMemoryMB", polled_mem_bytes / 1024 / 1024); - ResetPollHistory(true /* keep_last_sample */); - last_dump_memory_total_ = polled_mem_bytes; - on_peak_detected_callback_.Run(); -} - -bool MemoryPeakDetector::DetectPeakUsingSlidingWindowStddev( - uint64_t polled_mem_bytes) { - DCHECK(polled_mem_bytes); - samples_bytes_[samples_index_] = polled_mem_bytes; - samples_index_ = (samples_index_ + 1) % kSlidingWindowNumSamples; - float mean = 0; - for (uint32_t i = 0; i < kSlidingWindowNumSamples; ++i) { - if (samples_bytes_[i] == 0) - return false; // Not enough samples to detect peaks. - mean += samples_bytes_[i]; - } - mean /= kSlidingWindowNumSamples; - float variance = 0; - for (uint32_t i = 0; i < kSlidingWindowNumSamples; ++i) { - const float deviation = samples_bytes_[i] - mean; - variance += deviation * deviation; - } - variance /= kSlidingWindowNumSamples; - - // If stddev is less than 0.2% then we consider that the process is inactive. - if (variance < (mean / 500) * (mean / 500)) - return false; - - // (mean + 3.69 * stddev) corresponds to a value that is higher than current - // sample with 99.99% probability. - const float cur_sample_deviation = polled_mem_bytes - mean; - return cur_sample_deviation * cur_sample_deviation > (3.69 * 3.69 * variance); -} - -void MemoryPeakDetector::ResetPollHistory(bool keep_last_sample) { - // TODO(primiano,ssid): this logic should probably be revisited. In the case - // of Android, the browser process sees the total of all processes memory in - // the same peak detector instance. Perhaps the best thing to do here is to - // keep the window of samples around and just bump the skip_polls_. - last_dump_memory_total_ = 0; - if (keep_last_sample) { - const uint32_t prev_index = - samples_index_ > 0 ? samples_index_ - 1 : kSlidingWindowNumSamples - 1; - last_dump_memory_total_ = samples_bytes_[prev_index]; - } - memset(samples_bytes_, 0, sizeof(samples_bytes_)); - samples_index_ = 0; - skip_polls_ = 0; - if (config_.polling_interval_ms > 0) { - skip_polls_ = - (config_.min_time_between_peaks_ms + config_.polling_interval_ms - 1) / - config_.polling_interval_ms; - } -} - -void MemoryPeakDetector::SetStaticThresholdForTesting( - uint64_t static_threshold_bytes) { - DCHECK_EQ(DISABLED, state_); - static_threshold_bytes_ = static_threshold_bytes; -} - -MemoryPeakDetector::MemoryPeakDetector::Config::Config() - : Config(0, 0, false) {} - -MemoryPeakDetector::MemoryPeakDetector::Config::Config( - uint32_t polling_interval_ms, - uint32_t min_time_between_peaks_ms, - bool enable_verbose_poll_tracing) - : polling_interval_ms(polling_interval_ms), - min_time_between_peaks_ms(min_time_between_peaks_ms), - enable_verbose_poll_tracing(enable_verbose_poll_tracing) {} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_peak_detector.h b/base/trace_event/memory_peak_detector.h deleted file mode 100644 index bbe205b..0000000 --- a/base/trace_event/memory_peak_detector.h +++ /dev/null
@@ -1,184 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ -#define BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_ - -#include <stdint.h> - -#include <memory> -#include <vector> - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" - -namespace base { - -class SequencedTaskRunner; - -namespace trace_event { - -struct MemoryDumpProviderInfo; - -// Detects temporally local memory peaks. Peak detection is based on -// continuously querying memory usage using MemoryDumpprovider(s) that support -// fast polling (e.g., ProcessMetricsDumpProvider which under the hoods reads -// /proc/PID/statm on Linux) and using a combination of: -// - An static threshold (currently 1% of total system memory). -// - Sliding window stddev analysis. -// Design doc: https://goo.gl/0kOU4A . -// This class is NOT thread-safe, the caller has to ensure linearization of -// the calls to the public methods. In any case, the public methods do NOT have -// to be called from the |task_runner| on which the polling tasks run. -class BASE_EXPORT MemoryPeakDetector { - public: - using OnPeakDetectedCallback = RepeatingClosure; - using DumpProvidersList = std::vector<scoped_refptr<MemoryDumpProviderInfo>>; - using GetDumpProvidersFunction = RepeatingCallback<void(DumpProvidersList*)>; - - enum State { - NOT_INITIALIZED = 0, // Before Setup() - DISABLED, // Before Start() or after Stop(). - ENABLED, // After Start() but no dump_providers_ are available. - RUNNING // After Start(). The PollMemoryAndDetectPeak() task is scheduled. - }; - - // Peak detector configuration, passed to Start(). - struct BASE_EXPORT Config { - Config(); - Config(uint32_t polling_interval_ms, - uint32_t min_time_between_peaks_ms, - bool enable_verbose_poll_tracing); - - // The rate at which memory will be polled. Polls will happen on the task - // runner passed to Setup(). - uint32_t polling_interval_ms; - - // Two consecutive peak detection callbacks will happen at least - // |min_time_between_peaks_ms| apart from each other. - uint32_t min_time_between_peaks_ms; - - // When enabled causes a TRACE_COUNTER event to be injected in the trace - // for each poll (if tracing is enabled). - bool enable_verbose_poll_tracing; - }; - - static MemoryPeakDetector* GetInstance(); - - // Configures the peak detector, binding the polling tasks on the given - // thread. Setup() can be called several times, provided that: (1) Stop() - // is called; (2a) the previous task_runner is flushed or (2b) the task_runner - // remains the same. - // GetDumpProvidersFunction: is the function that will be invoked to get - // an updated list of polling-capable dump providers. This is really just - // MemoryDumpManager::GetDumpProvidersForPolling, but this extra level of - // indirection allows easier testing. - // SequencedTaskRunner: the task runner where PollMemoryAndDetectPeak() will - // be periodically called. - // OnPeakDetectedCallback: a callback that will be invoked on the - // given task runner when a memory peak is detected. - void Setup(const GetDumpProvidersFunction&, - const scoped_refptr<SequencedTaskRunner>&, - const OnPeakDetectedCallback&); - - // Releases the |task_runner_| and the bound callbacks. - void TearDown(); - - // This posts a task onto the passed task runner which refreshes the list of - // dump providers via the GetDumpProvidersFunction. If at least one dump - // provider is available, this starts immediately polling on the task runner. - // If not, the detector remains in the ENABLED state and will start polling - // automatically (i.e. without requiring another call to Start()) on the - // next call to NotifyMemoryDumpProvidersChanged(). - void Start(Config); - - // Stops the polling on the task runner (if was active at all). This doesn't - // wait for the task runner to drain pending tasks, so it is possible that - // a polling will happen concurrently (or in the immediate future) with the - // Stop() call. It is responsibility of the caller to drain or synchronize - // with the task runner. - void Stop(); - - // If Start()-ed, prevents that a peak callback is triggered before the next - // |min_time_between_peaks_ms|. No-op if the peak detector is not enabled. - void Throttle(); - - // Used by MemoryDumpManager to notify that the list of polling-capable dump - // providers has changed. The peak detector will reload the list on the next - // polling task. This function can be called before Setup(), in which - // case will be just a no-op. - void NotifyMemoryDumpProvidersChanged(); - - void SetStaticThresholdForTesting(uint64_t static_threshold_bytes); - - private: - friend class MemoryPeakDetectorTest; - - static constexpr uint32_t kSlidingWindowNumSamples = 50; - - MemoryPeakDetector(); - ~MemoryPeakDetector(); - - // All these methods are always called on the |task_runner_|. - void StartInternal(Config); - void StopInternal(); - void TearDownInternal(); - void ReloadDumpProvidersAndStartPollingIfNeeded(); - void PollMemoryAndDetectPeak(uint32_t expected_generation); - bool DetectPeakUsingSlidingWindowStddev(uint64_t last_sample_bytes); - void ResetPollHistory(bool keep_last_sample = false); - - // It is safe to call these testing methods only on the |task_runner_|. - State state_for_testing() const { return state_; } - uint32_t poll_tasks_count_for_testing() const { - return poll_tasks_count_for_testing_; - } - - // The task runner where all the internal calls are posted onto. This field - // must be NOT be accessed by the tasks posted on the |task_runner_| because - // there might still be outstanding tasks on the |task_runner_| while this - // refptr is reset. This can only be safely accessed by the public methods - // above, which the client of this class is supposed to call sequentially. - scoped_refptr<SequencedTaskRunner> task_runner_; - - // After the Setup() call, the fields below, must be accessed only from - // the |task_runner_|. - - // Bound function to get an updated list of polling-capable dump providers. - GetDumpProvidersFunction get_dump_providers_function_; - - // The callback to invoke when peaks are detected. - OnPeakDetectedCallback on_peak_detected_callback_; - - // List of polling-aware dump providers to invoke upon each poll. - DumpProvidersList dump_providers_; - - // The generation is incremented every time the |state_| is changed and causes - // PollMemoryAndDetectPeak() to early out if the posted task doesn't match the - // most recent |generation_|. This allows to drop on the floor outstanding - // PostDelayedTask that refer to an old sequence that was later Stop()-ed or - // disabled because of NotifyMemoryDumpProvidersChanged(). - uint32_t generation_; - - State state_; - - // Config passed to Start(), only valid when |state_| = {ENABLED, RUNNING}. - Config config_; - - uint64_t static_threshold_bytes_; - uint32_t skip_polls_; - uint64_t last_dump_memory_total_; - uint64_t samples_bytes_[kSlidingWindowNumSamples]; - uint32_t samples_index_; - uint32_t poll_tasks_count_for_testing_; - - DISALLOW_COPY_AND_ASSIGN(MemoryPeakDetector); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_
diff --git a/base/trace_event/memory_usage_estimator.cc b/base/trace_event/memory_usage_estimator.cc deleted file mode 100644 index c769d5b..0000000 --- a/base/trace_event/memory_usage_estimator.cc +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/memory_usage_estimator.h" - -namespace base { -namespace trace_event { - -template size_t EstimateMemoryUsage(const std::string&); -template size_t EstimateMemoryUsage(const string16&); - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/memory_usage_estimator.h b/base/trace_event/memory_usage_estimator.h deleted file mode 100644 index 214c64a..0000000 --- a/base/trace_event/memory_usage_estimator.h +++ /dev/null
@@ -1,654 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_ -#define BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_ - -#include <stdint.h> - -#include <array> -#include <deque> -#include <list> -#include <map> -#include <memory> -#include <queue> -#include <set> -#include <stack> -#include <string> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -#include "base/base_export.h" -#include "base/containers/circular_deque.h" -#include "base/containers/flat_map.h" -#include "base/containers/flat_set.h" -#include "base/containers/linked_list.h" -#include "base/containers/mru_cache.h" -#include "base/containers/queue.h" -#include "base/stl_util.h" -#include "base/strings/string16.h" -#include "base/template_util.h" - -// Composable memory usage estimators. -// -// This file defines set of EstimateMemoryUsage(object) functions that return -// approximate memory usage of their argument. -// -// The ultimate goal is to make memory usage estimation for a class simply a -// matter of aggregating EstimateMemoryUsage() results over all fields. -// -// That is achieved via composability: if EstimateMemoryUsage() is defined -// for T then EstimateMemoryUsage() is also defined for any combination of -// containers holding T (e.g. std::map<int, std::vector<T>>). -// -// There are two ways of defining EstimateMemoryUsage() for a type: -// -// 1. As a global function 'size_t EstimateMemoryUsage(T)' in -// in base::trace_event namespace. -// -// 2. As 'size_t T::EstimateMemoryUsage() const' method. In this case -// EstimateMemoryUsage(T) function in base::trace_event namespace is -// provided automatically. -// -// Here is an example implementation: -// -// size_t foo::bar::MyClass::EstimateMemoryUsage() const { -// return base::trace_event::EstimateMemoryUsage(name_) + -// base::trace_event::EstimateMemoryUsage(id_) + -// base::trace_event::EstimateMemoryUsage(items_); -// } -// -// The approach is simple: first call EstimateMemoryUsage() on all members, -// then recursively fix compilation errors that are caused by types not -// implementing EstimateMemoryUsage(). - -namespace base { -namespace trace_event { - -// Declarations - -// If T declares 'EstimateMemoryUsage() const' member function, then -// global function EstimateMemoryUsage(T) is available, and just calls -// the member function. -template <class T> -auto EstimateMemoryUsage(const T& object) - -> decltype(object.EstimateMemoryUsage()); - -// String - -template <class C, class T, class A> -size_t EstimateMemoryUsage(const std::basic_string<C, T, A>& string); - -// Arrays - -template <class T, size_t N> -size_t EstimateMemoryUsage(const std::array<T, N>& array); - -template <class T, size_t N> -size_t EstimateMemoryUsage(T (&array)[N]); - -template <class T> -size_t EstimateMemoryUsage(const T* array, size_t array_length); - -// std::unique_ptr - -template <class T, class D> -size_t EstimateMemoryUsage(const std::unique_ptr<T, D>& ptr); - -template <class T, class D> -size_t EstimateMemoryUsage(const std::unique_ptr<T[], D>& array, - size_t array_length); - -// std::shared_ptr - -template <class T> -size_t EstimateMemoryUsage(const std::shared_ptr<T>& ptr); - -// Containers - -template <class F, class S> -size_t EstimateMemoryUsage(const std::pair<F, S>& pair); - -template <class T, class A> -size_t EstimateMemoryUsage(const std::vector<T, A>& vector); - -template <class T, class A> -size_t EstimateMemoryUsage(const std::list<T, A>& list); - -template <class T> -size_t EstimateMemoryUsage(const base::LinkedList<T>& list); - -template <class T, class C, class A> -size_t EstimateMemoryUsage(const std::set<T, C, A>& set); - -template <class T, class C, class A> -size_t EstimateMemoryUsage(const std::multiset<T, C, A>& set); - -template <class K, class V, class C, class A> -size_t EstimateMemoryUsage(const std::map<K, V, C, A>& map); - -template <class K, class V, class C, class A> -size_t EstimateMemoryUsage(const std::multimap<K, V, C, A>& map); - -template <class T, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_set<T, H, KE, A>& set); - -template <class T, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_multiset<T, H, KE, A>& set); - -template <class K, class V, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_map<K, V, H, KE, A>& map); - -template <class K, class V, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map); - -template <class T, class A> -size_t EstimateMemoryUsage(const std::deque<T, A>& deque); - -template <class T, class C> -size_t EstimateMemoryUsage(const std::queue<T, C>& queue); - -template <class T, class C> -size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue); - -template <class T, class C> -size_t EstimateMemoryUsage(const std::stack<T, C>& stack); - -template <class T> -size_t EstimateMemoryUsage(const base::circular_deque<T>& deque); - -template <class T, class C> -size_t EstimateMemoryUsage(const base::flat_set<T, C>& set); - -template <class K, class V, class C> -size_t EstimateMemoryUsage(const base::flat_map<K, V, C>& map); - -template <class Key, - class Payload, - class HashOrComp, - template <typename, typename, typename> class Map> -size_t EstimateMemoryUsage(const MRUCacheBase<Key, Payload, HashOrComp, Map>&); - -// TODO(dskiba): -// std::forward_list - -// Definitions - -namespace internal { - -// HasEMU<T>::value is true iff EstimateMemoryUsage(T) is available. -// (This is the default version, which is false.) -template <class T, class X = void> -struct HasEMU : std::false_type {}; - -// This HasEMU specialization is only picked up if there exists function -// EstimateMemoryUsage(const T&) that returns size_t. Simpler ways to -// achieve this don't work on MSVC. -template <class T> -struct HasEMU< - T, - typename std::enable_if<std::is_same< - size_t, - decltype(EstimateMemoryUsage(std::declval<const T&>()))>::value>::type> - : std::true_type {}; - -// EMUCaller<T> does three things: -// 1. Defines Call() method that calls EstimateMemoryUsage(T) if it's -// available. -// 2. If EstimateMemoryUsage(T) is not available, but T has trivial dtor -// (i.e. it's POD, integer, pointer, enum, etc.) then it defines Call() -// method that returns 0. This is useful for containers, which allocate -// memory regardless of T (also for cases like std::map<int, MyClass>). -// 3. Finally, if EstimateMemoryUsage(T) is not available, then it triggers -// a static_assert with a helpful message. That cuts numbers of errors -// considerably - if you just call EstimateMemoryUsage(T) but it's not -// available for T, then compiler will helpfully list *all* possible -// variants of it, with an explanation for each. -template <class T, class X = void> -struct EMUCaller { - // std::is_same<> below makes static_assert depend on T, in order to - // prevent it from asserting regardless instantiation. - static_assert(std::is_same<T, std::false_type>::value, - "Neither global function 'size_t EstimateMemoryUsage(T)' " - "nor member function 'size_t T::EstimateMemoryUsage() const' " - "is defined for the type."); - - static size_t Call(const T&) { return 0; } -}; - -template <class T> -struct EMUCaller<T, typename std::enable_if<HasEMU<T>::value>::type> { - static size_t Call(const T& value) { return EstimateMemoryUsage(value); } -}; - -template <template <class...> class Container, class I, class = void> -struct IsComplexIteratorForContainer : std::false_type {}; - -template <template <class...> class Container, class I> -struct IsComplexIteratorForContainer< - Container, - I, - std::enable_if_t<!std::is_pointer<I>::value && - base::internal::is_iterator<I>::value>> { - using value_type = typename std::iterator_traits<I>::value_type; - using container_type = Container<value_type>; - - // We use enum instead of static constexpr bool, beause we don't have inline - // variables until c++17. - // - // The downside is - value is not of type bool. - enum : bool { - value = - std::is_same<typename container_type::iterator, I>::value || - std::is_same<typename container_type::const_iterator, I>::value || - std::is_same<typename container_type::reverse_iterator, I>::value || - std::is_same<typename container_type::const_reverse_iterator, I>::value, - }; -}; - -template <class I, template <class...> class... Containers> -constexpr bool OneOfContainersComplexIterators() { - // We are forced to create a temporary variable to workaround a compilation - // error in msvs. - const bool all_tests[] = { - IsComplexIteratorForContainer<Containers, I>::value...}; - for (bool test : all_tests) - if (test) - return true; - return false; -} - -// std::array has an extra required template argument. We curry it. -template <class T> -using array_test_helper = std::array<T, 1>; - -template <class I> -constexpr bool IsStandardContainerComplexIterator() { - // TODO(dyaroshev): deal with maps iterators if there is a need. - // It requires to parse pairs into keys and values. - // TODO(dyaroshev): deal with unordered containers: they do not have reverse - // iterators. - return OneOfContainersComplexIterators< - I, array_test_helper, std::vector, std::deque, - /*std::forward_list,*/ std::list, std::set, std::multiset>(); -} - -// Work around MSVS bug. For some reason constexpr function doesn't work. -// However variable template does. -template <typename T> -constexpr bool IsKnownNonAllocatingType_v = - std::is_trivially_destructible<T>::value || - IsStandardContainerComplexIterator<T>(); - -template <class T> -struct EMUCaller< - T, - std::enable_if_t<!HasEMU<T>::value && IsKnownNonAllocatingType_v<T>>> { - static size_t Call(const T& value) { return 0; } -}; - -} // namespace internal - -// Proxy that deducts T and calls EMUCaller<T>. -// To be used by EstimateMemoryUsage() implementations for containers. -template <class T> -size_t EstimateItemMemoryUsage(const T& value) { - return internal::EMUCaller<T>::Call(value); -} - -template <class I> -size_t EstimateIterableMemoryUsage(const I& iterable) { - size_t memory_usage = 0; - for (const auto& item : iterable) { - memory_usage += EstimateItemMemoryUsage(item); - } - return memory_usage; -} - -// Global EstimateMemoryUsage(T) that just calls T::EstimateMemoryUsage(). -template <class T> -auto EstimateMemoryUsage(const T& object) - -> decltype(object.EstimateMemoryUsage()) { - static_assert( - std::is_same<decltype(object.EstimateMemoryUsage()), size_t>::value, - "'T::EstimateMemoryUsage() const' must return size_t."); - return object.EstimateMemoryUsage(); -} - -// String - -template <class C, class T, class A> -size_t EstimateMemoryUsage(const std::basic_string<C, T, A>& string) { - using string_type = std::basic_string<C, T, A>; - using value_type = typename string_type::value_type; - // C++11 doesn't leave much room for implementors - std::string can - // use short string optimization, but that's about it. We detect SSO - // by checking that c_str() points inside |string|. - const uint8_t* cstr = reinterpret_cast<const uint8_t*>(string.c_str()); - const uint8_t* inline_cstr = reinterpret_cast<const uint8_t*>(&string); - if (cstr >= inline_cstr && cstr < inline_cstr + sizeof(string)) { - // SSO string - return 0; - } - return (string.capacity() + 1) * sizeof(value_type); -} - -// Use explicit instantiations from the .cc file (reduces bloat). -extern template BASE_EXPORT size_t EstimateMemoryUsage(const std::string&); -extern template BASE_EXPORT size_t EstimateMemoryUsage(const string16&); - -// Arrays - -template <class T, size_t N> -size_t EstimateMemoryUsage(const std::array<T, N>& array) { - return EstimateIterableMemoryUsage(array); -} - -template <class T, size_t N> -size_t EstimateMemoryUsage(T (&array)[N]) { - return EstimateIterableMemoryUsage(array); -} - -template <class T> -size_t EstimateMemoryUsage(const T* array, size_t array_length) { - size_t memory_usage = sizeof(T) * array_length; - for (size_t i = 0; i != array_length; ++i) { - memory_usage += EstimateItemMemoryUsage(array[i]); - } - return memory_usage; -} - -// std::unique_ptr - -template <class T, class D> -size_t EstimateMemoryUsage(const std::unique_ptr<T, D>& ptr) { - return ptr ? (sizeof(T) + EstimateItemMemoryUsage(*ptr)) : 0; -} - -template <class T, class D> -size_t EstimateMemoryUsage(const std::unique_ptr<T[], D>& array, - size_t array_length) { - return EstimateMemoryUsage(array.get(), array_length); -} - -// std::shared_ptr - -template <class T> -size_t EstimateMemoryUsage(const std::shared_ptr<T>& ptr) { - auto use_count = ptr.use_count(); - if (use_count == 0) { - return 0; - } - // Model shared_ptr after libc++, - // see __shared_ptr_pointer from include/memory - struct SharedPointer { - void* vtbl; - long shared_owners; - long shared_weak_owners; - T* value; - }; - // If object of size S shared N > S times we prefer to (potentially) - // overestimate than to return 0. - return sizeof(SharedPointer) + - (EstimateItemMemoryUsage(*ptr) + (use_count - 1)) / use_count; -} - -// std::pair - -template <class F, class S> -size_t EstimateMemoryUsage(const std::pair<F, S>& pair) { - return EstimateItemMemoryUsage(pair.first) + - EstimateItemMemoryUsage(pair.second); -} - -// std::vector - -template <class T, class A> -size_t EstimateMemoryUsage(const std::vector<T, A>& vector) { - return sizeof(T) * vector.capacity() + EstimateIterableMemoryUsage(vector); -} - -// std::list - -template <class T, class A> -size_t EstimateMemoryUsage(const std::list<T, A>& list) { - using value_type = typename std::list<T, A>::value_type; - struct Node { - Node* prev; - Node* next; - value_type value; - }; - return sizeof(Node) * list.size() + - EstimateIterableMemoryUsage(list); -} - -template <class T> -size_t EstimateMemoryUsage(const base::LinkedList<T>& list) { - size_t memory_usage = 0u; - for (base::LinkNode<T>* node = list.head(); node != list.end(); - node = node->next()) { - // Since we increment by calling node = node->next() we know that node - // isn't nullptr. - memory_usage += EstimateMemoryUsage(*node->value()) + sizeof(T); - } - return memory_usage; -} - -// Tree containers - -template <class V> -size_t EstimateTreeMemoryUsage(size_t size) { - // Tree containers are modeled after libc++ - // (__tree_node from include/__tree) - struct Node { - Node* left; - Node* right; - Node* parent; - bool is_black; - V value; - }; - return sizeof(Node) * size; -} - -template <class T, class C, class A> -size_t EstimateMemoryUsage(const std::set<T, C, A>& set) { - using value_type = typename std::set<T, C, A>::value_type; - return EstimateTreeMemoryUsage<value_type>(set.size()) + - EstimateIterableMemoryUsage(set); -} - -template <class T, class C, class A> -size_t EstimateMemoryUsage(const std::multiset<T, C, A>& set) { - using value_type = typename std::multiset<T, C, A>::value_type; - return EstimateTreeMemoryUsage<value_type>(set.size()) + - EstimateIterableMemoryUsage(set); -} - -template <class K, class V, class C, class A> -size_t EstimateMemoryUsage(const std::map<K, V, C, A>& map) { - using value_type = typename std::map<K, V, C, A>::value_type; - return EstimateTreeMemoryUsage<value_type>(map.size()) + - EstimateIterableMemoryUsage(map); -} - -template <class K, class V, class C, class A> -size_t EstimateMemoryUsage(const std::multimap<K, V, C, A>& map) { - using value_type = typename std::multimap<K, V, C, A>::value_type; - return EstimateTreeMemoryUsage<value_type>(map.size()) + - EstimateIterableMemoryUsage(map); -} - -// HashMap containers - -namespace internal { - -// While hashtable containers model doesn't depend on STL implementation, one -// detail still crept in: bucket_count. It's used in size estimation, but its -// value after inserting N items is not predictable. -// This function is specialized by unittests to return constant value, thus -// excluding bucket_count from testing. -template <class V> -size_t HashMapBucketCountForTesting(size_t bucket_count) { - return bucket_count; -} - -template <class MruCacheType> -size_t DoEstimateMemoryUsageForMruCache(const MruCacheType& mru_cache) { - return EstimateMemoryUsage(mru_cache.ordering_) + - EstimateMemoryUsage(mru_cache.index_); -} - -} // namespace internal - -template <class V> -size_t EstimateHashMapMemoryUsage(size_t bucket_count, size_t size) { - // Hashtable containers are modeled after libc++ - // (__hash_node from include/__hash_table) - struct Node { - void* next; - size_t hash; - V value; - }; - using Bucket = void*; - bucket_count = internal::HashMapBucketCountForTesting<V>(bucket_count); - return sizeof(Bucket) * bucket_count + sizeof(Node) * size; -} - -template <class K, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_set<K, H, KE, A>& set) { - using value_type = typename std::unordered_set<K, H, KE, A>::value_type; - return EstimateHashMapMemoryUsage<value_type>(set.bucket_count(), - set.size()) + - EstimateIterableMemoryUsage(set); -} - -template <class K, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_multiset<K, H, KE, A>& set) { - using value_type = typename std::unordered_multiset<K, H, KE, A>::value_type; - return EstimateHashMapMemoryUsage<value_type>(set.bucket_count(), - set.size()) + - EstimateIterableMemoryUsage(set); -} - -template <class K, class V, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_map<K, V, H, KE, A>& map) { - using value_type = typename std::unordered_map<K, V, H, KE, A>::value_type; - return EstimateHashMapMemoryUsage<value_type>(map.bucket_count(), - map.size()) + - EstimateIterableMemoryUsage(map); -} - -template <class K, class V, class H, class KE, class A> -size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map) { - using value_type = - typename std::unordered_multimap<K, V, H, KE, A>::value_type; - return EstimateHashMapMemoryUsage<value_type>(map.bucket_count(), - map.size()) + - EstimateIterableMemoryUsage(map); -} - -// std::deque - -template <class T, class A> -size_t EstimateMemoryUsage(const std::deque<T, A>& deque) { -// Since std::deque implementations are wildly different -// (see crbug.com/674287), we can't have one "good enough" -// way to estimate. - -// kBlockSize - minimum size of a block, in bytes -// kMinBlockLength - number of elements in a block -// if sizeof(T) > kBlockSize -#if defined(_LIBCPP_VERSION) - size_t kBlockSize = 4096; - size_t kMinBlockLength = 16; -#elif defined(__GLIBCXX__) - size_t kBlockSize = 512; - size_t kMinBlockLength = 1; -#elif defined(_MSC_VER) - size_t kBlockSize = 16; - size_t kMinBlockLength = 1; -#else - size_t kBlockSize = 0; - size_t kMinBlockLength = 1; -#endif - - size_t block_length = - (sizeof(T) > kBlockSize) ? kMinBlockLength : kBlockSize / sizeof(T); - - size_t blocks = (deque.size() + block_length - 1) / block_length; - -#if defined(__GLIBCXX__) - // libstdc++: deque always has at least one block - if (!blocks) - blocks = 1; -#endif - -#if defined(_LIBCPP_VERSION) - // libc++: deque keeps at most two blocks when it shrinks, - // so even if the size is zero, deque might be holding up - // to 4096 * 2 bytes. One way to know whether deque has - // ever allocated (and hence has 1 or 2 blocks) is to check - // iterator's pointer. Non-zero value means that deque has - // at least one block. - if (!blocks && deque.begin().operator->()) - blocks = 1; -#endif - - return (blocks * block_length * sizeof(T)) + - EstimateIterableMemoryUsage(deque); -} - -// Container adapters - -template <class T, class C> -size_t EstimateMemoryUsage(const std::queue<T, C>& queue) { - return EstimateMemoryUsage(GetUnderlyingContainer(queue)); -} - -template <class T, class C> -size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue) { - return EstimateMemoryUsage(GetUnderlyingContainer(queue)); -} - -template <class T, class C> -size_t EstimateMemoryUsage(const std::stack<T, C>& stack) { - return EstimateMemoryUsage(GetUnderlyingContainer(stack)); -} - -// base::circular_deque - -template <class T> -size_t EstimateMemoryUsage(const base::circular_deque<T>& deque) { - return sizeof(T) * deque.capacity() + EstimateIterableMemoryUsage(deque); -} - -// Flat containers - -template <class T, class C> -size_t EstimateMemoryUsage(const base::flat_set<T, C>& set) { - using value_type = typename base::flat_set<T, C>::value_type; - return sizeof(value_type) * set.capacity() + EstimateIterableMemoryUsage(set); -} - -template <class K, class V, class C> -size_t EstimateMemoryUsage(const base::flat_map<K, V, C>& map) { - using value_type = typename base::flat_map<K, V, C>::value_type; - return sizeof(value_type) * map.capacity() + EstimateIterableMemoryUsage(map); -} - -template <class Key, - class Payload, - class HashOrComp, - template <typename, typename, typename> class Map> -size_t EstimateMemoryUsage( - const MRUCacheBase<Key, Payload, HashOrComp, Map>& mru_cache) { - return internal::DoEstimateMemoryUsageForMruCache(mru_cache); -} - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc deleted file mode 100644 index d565b47..0000000 --- a/base/trace_event/process_memory_dump.cc +++ /dev/null
@@ -1,545 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/process_memory_dump.h" - -#include <errno.h> - -#include <vector> - -#include "base/memory/ptr_util.h" -#include "base/memory/shared_memory_tracker.h" -#include "base/process/process_metrics.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/heap_profiler_heap_dump_writer.h" -#include "base/trace_event/heap_profiler_serialization_state.h" -#include "base/trace_event/memory_infra_background_whitelist.h" -#include "base/trace_event/trace_event_argument.h" -#include "base/unguessable_token.h" -#include "build_config.h" - -#if defined(OS_IOS) -#include <mach/vm_page_size.h> -#endif - -#if defined(OS_POSIX) || defined(OS_FUCHSIA) -#include <sys/mman.h> -#endif - -#if defined(OS_WIN) -#include <windows.h> // Must be in front of other Windows header files - -#include <Psapi.h> -#endif - -namespace base { -namespace trace_event { - -namespace { - -const char kEdgeTypeOwnership[] = "ownership"; - -std::string GetSharedGlobalAllocatorDumpName( - const MemoryAllocatorDumpGuid& guid) { - return "global/" + guid.ToString(); -} - -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) -size_t GetSystemPageCount(size_t mapped_size, size_t page_size) { - return (mapped_size + page_size - 1) / page_size; -} -#endif - -UnguessableToken GetTokenForCurrentProcess() { - static UnguessableToken instance = UnguessableToken::Create(); - return instance; -} - -} // namespace - -// static -bool ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = false; - -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) -// static -size_t ProcessMemoryDump::GetSystemPageSize() { -#if defined(OS_IOS) - // On iOS, getpagesize() returns the user page sizes, but for allocating - // arrays for mincore(), kernel page sizes is needed. Use vm_kernel_page_size - // as recommended by Apple, https://forums.developer.apple.com/thread/47532/. - // Refer to http://crbug.com/542671 and Apple rdar://23651782 - return vm_kernel_page_size; -#else - return base::GetPageSize(); -#endif // defined(OS_IOS) -} - -// static -size_t ProcessMemoryDump::CountResidentBytes(void* start_address, - size_t mapped_size) { - const size_t page_size = GetSystemPageSize(); - const uintptr_t start_pointer = reinterpret_cast<uintptr_t>(start_address); - DCHECK_EQ(0u, start_pointer % page_size); - - size_t offset = 0; - size_t total_resident_pages = 0; - bool failure = false; - - // An array as large as number of pages in memory segment needs to be passed - // to the query function. To avoid allocating a large array, the given block - // of memory is split into chunks of size |kMaxChunkSize|. - const size_t kMaxChunkSize = 8 * 1024 * 1024; - size_t max_vec_size = - GetSystemPageCount(std::min(mapped_size, kMaxChunkSize), page_size); -#if defined(OS_WIN) - std::unique_ptr<PSAPI_WORKING_SET_EX_INFORMATION[]> vec( - new PSAPI_WORKING_SET_EX_INFORMATION[max_vec_size]); -#elif defined(OS_MACOSX) - std::unique_ptr<char[]> vec(new char[max_vec_size]); -#elif defined(OS_POSIX) || defined(OS_FUCHSIA) - std::unique_ptr<unsigned char[]> vec(new unsigned char[max_vec_size]); -#endif - - while (offset < mapped_size) { - uintptr_t chunk_start = (start_pointer + offset); - const size_t chunk_size = std::min(mapped_size - offset, kMaxChunkSize); - const size_t page_count = GetSystemPageCount(chunk_size, page_size); - size_t resident_page_count = 0; -#if defined(OS_WIN) - for (size_t i = 0; i < page_count; i++) { - vec[i].VirtualAddress = - reinterpret_cast<void*>(chunk_start + i * page_size); - } - DWORD vec_size = static_cast<DWORD>( - page_count * sizeof(PSAPI_WORKING_SET_EX_INFORMATION)); - failure = !QueryWorkingSetEx(GetCurrentProcess(), vec.get(), vec_size); - - for (size_t i = 0; i < page_count; i++) - resident_page_count += vec[i].VirtualAttributes.Valid; -#elif defined(OS_FUCHSIA) - // TODO(fuchsia): Port, see https://crbug.com/706592. - ALLOW_UNUSED_LOCAL(chunk_start); - ALLOW_UNUSED_LOCAL(page_count); -#elif defined(OS_MACOSX) - // mincore in MAC does not fail with EAGAIN. - failure = - !!mincore(reinterpret_cast<void*>(chunk_start), chunk_size, vec.get()); - for (size_t i = 0; i < page_count; i++) - resident_page_count += vec[i] & MINCORE_INCORE ? 1 : 0; -#elif defined(OS_POSIX) - int error_counter = 0; - int result = 0; - // HANDLE_EINTR tries for 100 times. So following the same pattern. - do { - result = -#if defined(OS_AIX) - mincore(reinterpret_cast<char*>(chunk_start), chunk_size, - reinterpret_cast<char*>(vec.get())); -#else - mincore(reinterpret_cast<void*>(chunk_start), chunk_size, vec.get()); -#endif - } while (result == -1 && errno == EAGAIN && error_counter++ < 100); - failure = !!result; - - for (size_t i = 0; i < page_count; i++) - resident_page_count += vec[i] & 1; -#endif - - if (failure) - break; - - total_resident_pages += resident_page_count * page_size; - offset += kMaxChunkSize; - } - - DCHECK(!failure); - if (failure) { - total_resident_pages = 0; - LOG(ERROR) << "CountResidentBytes failed. The resident size is invalid"; - } - return total_resident_pages; -} - -// static -base::Optional<size_t> ProcessMemoryDump::CountResidentBytesInSharedMemory( - void* start_address, - size_t mapped_size) { -#if defined(OS_MACOSX) && !defined(OS_IOS) - // On macOS, use mach_vm_region instead of mincore for performance - // (crbug.com/742042). - mach_vm_size_t dummy_size = 0; - mach_vm_address_t address = - reinterpret_cast<mach_vm_address_t>(start_address); - vm_region_top_info_data_t info; - MachVMRegionResult result = - GetTopInfo(mach_task_self(), &dummy_size, &address, &info); - if (result == MachVMRegionResult::Error) { - LOG(ERROR) << "CountResidentBytesInSharedMemory failed. The resident size " - "is invalid"; - return base::Optional<size_t>(); - } - - size_t resident_pages = - info.private_pages_resident + info.shared_pages_resident; - - // On macOS, measurements for private memory footprint overcount by - // faulted pages in anonymous shared memory. To discount for this, we touch - // all the resident pages in anonymous shared memory here, thus making them - // faulted as well. This relies on two assumptions: - // - // 1) Consumers use shared memory from front to back. Thus, if there are - // (N) resident pages, those pages represent the first N * PAGE_SIZE bytes in - // the shared memory region. - // - // 2) This logic is run shortly before the logic that calculates - // phys_footprint, thus ensuring that the discrepancy between faulted and - // resident pages is minimal. - // - // The performance penalty is expected to be small. - // - // * Most of the time, we expect the pages to already be resident and faulted, - // thus incurring a cache penalty read hit [since we read from each resident - // page]. - // - // * Rarely, we expect the pages to be resident but not faulted, resulting in - // soft faults + cache penalty. - // - // * If assumption (1) is invalid, this will potentially fault some - // previously non-resident pages, thus increasing memory usage, without fixing - // the accounting. - // - // Sanity check in case the mapped size is less than the total size of the - // region. - size_t pages_to_fault = - std::min(resident_pages, (mapped_size + PAGE_SIZE - 1) / PAGE_SIZE); - - volatile char* base_address = static_cast<char*>(start_address); - for (size_t i = 0; i < pages_to_fault; ++i) { - // Reading from a volatile is a visible side-effect for the purposes of - // optimization. This guarantees that the optimizer will not kill this line. - base_address[i * PAGE_SIZE]; - } - - return resident_pages * PAGE_SIZE; -#else - return CountResidentBytes(start_address, mapped_size); -#endif // defined(OS_MACOSX) && !defined(OS_IOS) -} - -#endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) - -ProcessMemoryDump::ProcessMemoryDump( - scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state, - const MemoryDumpArgs& dump_args) - : process_token_(GetTokenForCurrentProcess()), - heap_profiler_serialization_state_( - std::move(heap_profiler_serialization_state)), - dump_args_(dump_args) {} - -ProcessMemoryDump::~ProcessMemoryDump() = default; -ProcessMemoryDump::ProcessMemoryDump(ProcessMemoryDump&& other) = default; -ProcessMemoryDump& ProcessMemoryDump::operator=(ProcessMemoryDump&& other) = - default; - -MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( - const std::string& absolute_name) { - return AddAllocatorDumpInternal(std::make_unique<MemoryAllocatorDump>( - absolute_name, dump_args_.level_of_detail, GetDumpId(absolute_name))); -} - -MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( - const std::string& absolute_name, - const MemoryAllocatorDumpGuid& guid) { - return AddAllocatorDumpInternal(std::make_unique<MemoryAllocatorDump>( - absolute_name, dump_args_.level_of_detail, guid)); -} - -MemoryAllocatorDump* ProcessMemoryDump::AddAllocatorDumpInternal( - std::unique_ptr<MemoryAllocatorDump> mad) { - // In background mode return the black hole dump, if invalid dump name is - // given. - if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND && - !IsMemoryAllocatorDumpNameWhitelisted(mad->absolute_name())) { - return GetBlackHoleMad(); - } - - auto insertion_result = allocator_dumps_.insert( - std::make_pair(mad->absolute_name(), std::move(mad))); - MemoryAllocatorDump* inserted_mad = insertion_result.first->second.get(); - DCHECK(insertion_result.second) << "Duplicate name: " - << inserted_mad->absolute_name(); - return inserted_mad; -} - -MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump( - const std::string& absolute_name) const { - auto it = allocator_dumps_.find(absolute_name); - if (it != allocator_dumps_.end()) - return it->second.get(); - if (black_hole_mad_) - return black_hole_mad_.get(); - return nullptr; -} - -MemoryAllocatorDump* ProcessMemoryDump::GetOrCreateAllocatorDump( - const std::string& absolute_name) { - MemoryAllocatorDump* mad = GetAllocatorDump(absolute_name); - return mad ? mad : CreateAllocatorDump(absolute_name); -} - -MemoryAllocatorDump* ProcessMemoryDump::CreateSharedGlobalAllocatorDump( - const MemoryAllocatorDumpGuid& guid) { - // A shared allocator dump can be shared within a process and the guid could - // have been created already. - MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid); - if (mad && mad != black_hole_mad_.get()) { - // The weak flag is cleared because this method should create a non-weak - // dump. - mad->clear_flags(MemoryAllocatorDump::Flags::WEAK); - return mad; - } - return CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid); -} - -MemoryAllocatorDump* ProcessMemoryDump::CreateWeakSharedGlobalAllocatorDump( - const MemoryAllocatorDumpGuid& guid) { - MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid); - if (mad && mad != black_hole_mad_.get()) - return mad; - mad = CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid); - mad->set_flags(MemoryAllocatorDump::Flags::WEAK); - return mad; -} - -MemoryAllocatorDump* ProcessMemoryDump::GetSharedGlobalAllocatorDump( - const MemoryAllocatorDumpGuid& guid) const { - return GetAllocatorDump(GetSharedGlobalAllocatorDumpName(guid)); -} - -void ProcessMemoryDump::DumpHeapUsage( - const std::unordered_map<base::trace_event::AllocationContext, - base::trace_event::AllocationMetrics>& - metrics_by_context, - base::trace_event::TraceEventMemoryOverhead& overhead, - const char* allocator_name) { - // The heap profiler serialization state can be null here if heap profiler was - // enabled when a process dump is in progress. - if (heap_profiler_serialization_state() && !metrics_by_context.empty()) { - DCHECK_EQ(0ul, heap_dumps_.count(allocator_name)); - std::unique_ptr<TracedValue> heap_dump = ExportHeapDump( - metrics_by_context, *heap_profiler_serialization_state()); - heap_dumps_[allocator_name] = std::move(heap_dump); - } - - std::string base_name = base::StringPrintf("tracing/heap_profiler_%s", - allocator_name); - overhead.DumpInto(base_name.c_str(), this); -} - -void ProcessMemoryDump::SetAllocatorDumpsForSerialization( - std::vector<std::unique_ptr<MemoryAllocatorDump>> dumps) { - DCHECK(allocator_dumps_.empty()); - for (std::unique_ptr<MemoryAllocatorDump>& dump : dumps) - AddAllocatorDumpInternal(std::move(dump)); -} - -std::vector<ProcessMemoryDump::MemoryAllocatorDumpEdge> -ProcessMemoryDump::GetAllEdgesForSerialization() const { - std::vector<MemoryAllocatorDumpEdge> edges; - edges.reserve(allocator_dumps_edges_.size()); - for (const auto& it : allocator_dumps_edges_) - edges.push_back(it.second); - return edges; -} - -void ProcessMemoryDump::SetAllEdgesForSerialization( - const std::vector<ProcessMemoryDump::MemoryAllocatorDumpEdge>& edges) { - DCHECK(allocator_dumps_edges_.empty()); - for (const MemoryAllocatorDumpEdge& edge : edges) { - auto it_and_inserted = allocator_dumps_edges_.emplace(edge.source, edge); - DCHECK(it_and_inserted.second); - } -} - -void ProcessMemoryDump::Clear() { - allocator_dumps_.clear(); - allocator_dumps_edges_.clear(); - heap_dumps_.clear(); -} - -void ProcessMemoryDump::TakeAllDumpsFrom(ProcessMemoryDump* other) { - // Moves the ownership of all MemoryAllocatorDump(s) contained in |other| - // into this ProcessMemoryDump, checking for duplicates. - for (auto& it : other->allocator_dumps_) - AddAllocatorDumpInternal(std::move(it.second)); - other->allocator_dumps_.clear(); - - // Move all the edges. - allocator_dumps_edges_.insert(other->allocator_dumps_edges_.begin(), - other->allocator_dumps_edges_.end()); - other->allocator_dumps_edges_.clear(); - - for (auto& it : other->heap_dumps_) { - DCHECK_EQ(0ul, heap_dumps_.count(it.first)); - heap_dumps_.insert(std::make_pair(it.first, std::move(it.second))); - } - other->heap_dumps_.clear(); -} - -void ProcessMemoryDump::SerializeAllocatorDumpsInto(TracedValue* value) const { - if (allocator_dumps_.size() > 0) { - value->BeginDictionary("allocators"); - for (const auto& allocator_dump_it : allocator_dumps_) - allocator_dump_it.second->AsValueInto(value); - value->EndDictionary(); - } - - value->BeginArray("allocators_graph"); - for (const auto& it : allocator_dumps_edges_) { - const MemoryAllocatorDumpEdge& edge = it.second; - value->BeginDictionary(); - value->SetString("source", edge.source.ToString()); - value->SetString("target", edge.target.ToString()); - value->SetInteger("importance", edge.importance); - value->SetString("type", kEdgeTypeOwnership); - value->EndDictionary(); - } - value->EndArray(); -} - -void ProcessMemoryDump::SerializeHeapProfilerDumpsInto( - TracedValue* value) const { - if (heap_dumps_.size() == 0) - return; - value->BeginDictionary("heaps"); - for (const auto& name_and_dump : heap_dumps_) - value->SetValueWithCopiedName(name_and_dump.first, *name_and_dump.second); - value->EndDictionary(); // "heaps" -} - -void ProcessMemoryDump::AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, - const MemoryAllocatorDumpGuid& target, - int importance) { - // This will either override an existing edge or create a new one. - auto it = allocator_dumps_edges_.find(source); - int max_importance = importance; - if (it != allocator_dumps_edges_.end()) { - DCHECK_EQ(target.ToUint64(), it->second.target.ToUint64()); - max_importance = std::max(importance, it->second.importance); - } - allocator_dumps_edges_[source] = {source, target, max_importance, - false /* overridable */}; -} - -void ProcessMemoryDump::AddOwnershipEdge( - const MemoryAllocatorDumpGuid& source, - const MemoryAllocatorDumpGuid& target) { - AddOwnershipEdge(source, target, 0 /* importance */); -} - -void ProcessMemoryDump::AddOverridableOwnershipEdge( - const MemoryAllocatorDumpGuid& source, - const MemoryAllocatorDumpGuid& target, - int importance) { - if (allocator_dumps_edges_.count(source) == 0) { - allocator_dumps_edges_[source] = {source, target, importance, - true /* overridable */}; - } else { - // An edge between the source and target already exits. So, do nothing here - // since the new overridable edge is implicitly overridden by a strong edge - // which was created earlier. - DCHECK(!allocator_dumps_edges_[source].overridable); - } -} - -void ProcessMemoryDump::CreateSharedMemoryOwnershipEdge( - const MemoryAllocatorDumpGuid& client_local_dump_guid, - const UnguessableToken& shared_memory_guid, - int importance) { - CreateSharedMemoryOwnershipEdgeInternal(client_local_dump_guid, - shared_memory_guid, importance, - false /*is_weak*/); -} - -void ProcessMemoryDump::CreateWeakSharedMemoryOwnershipEdge( - const MemoryAllocatorDumpGuid& client_local_dump_guid, - const UnguessableToken& shared_memory_guid, - int importance) { - CreateSharedMemoryOwnershipEdgeInternal( - client_local_dump_guid, shared_memory_guid, importance, true /*is_weak*/); -} - -void ProcessMemoryDump::CreateSharedMemoryOwnershipEdgeInternal( - const MemoryAllocatorDumpGuid& client_local_dump_guid, - const UnguessableToken& shared_memory_guid, - int importance, - bool is_weak) { - DCHECK(!shared_memory_guid.is_empty()); - // New model where the global dumps created by SharedMemoryTracker are used - // for the clients. - - // The guid of the local dump created by SharedMemoryTracker for the memory - // segment. - auto local_shm_guid = - GetDumpId(SharedMemoryTracker::GetDumpNameForTracing(shared_memory_guid)); - - // The dump guid of the global dump created by the tracker for the memory - // segment. - auto global_shm_guid = - SharedMemoryTracker::GetGlobalDumpIdForTracing(shared_memory_guid); - - // Create an edge between local dump of the client and the local dump of the - // SharedMemoryTracker. Do not need to create the dumps here since the tracker - // would create them. The importance is also required here for the case of - // single process mode. - AddOwnershipEdge(client_local_dump_guid, local_shm_guid, importance); - - // TODO(ssid): Handle the case of weak dumps here. This needs a new function - // GetOrCreaetGlobalDump() in PMD since we need to change the behavior of the - // created global dump. - // Create an edge that overrides the edge created by SharedMemoryTracker. - AddOwnershipEdge(local_shm_guid, global_shm_guid, importance); -} - -void ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source, - const std::string& target_node_name) { - // Do not create new dumps for suballocations in background mode. - if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) - return; - - std::string child_mad_name = target_node_name + "/__" + source.ToString(); - MemoryAllocatorDump* target_child_mad = CreateAllocatorDump(child_mad_name); - AddOwnershipEdge(source, target_child_mad->guid()); -} - -MemoryAllocatorDump* ProcessMemoryDump::GetBlackHoleMad() { - DCHECK(is_black_hole_non_fatal_for_testing_); - if (!black_hole_mad_) { - std::string name = "discarded"; - black_hole_mad_.reset(new MemoryAllocatorDump( - name, dump_args_.level_of_detail, GetDumpId(name))); - } - return black_hole_mad_.get(); -} - -MemoryAllocatorDumpGuid ProcessMemoryDump::GetDumpId( - const std::string& absolute_name) { - return MemoryAllocatorDumpGuid(StringPrintf( - "%s:%s", process_token().ToString().c_str(), absolute_name.c_str())); -} - -bool ProcessMemoryDump::MemoryAllocatorDumpEdge::operator==( - const MemoryAllocatorDumpEdge& other) const { - return source == other.source && target == other.target && - importance == other.importance && overridable == other.overridable; -} - -bool ProcessMemoryDump::MemoryAllocatorDumpEdge::operator!=( - const MemoryAllocatorDumpEdge& other) const { - return !(*this == other); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h deleted file mode 100644 index b2ce66f..0000000 --- a/base/trace_event/process_memory_dump.h +++ /dev/null
@@ -1,304 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ -#define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ - -#include <stddef.h> - -#include <map> -#include <unordered_map> -#include <vector> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/trace_event/heap_profiler_serialization_state.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/memory_allocator_dump_guid.h" -#include "base/trace_event/memory_dump_request_args.h" -#include "build_config.h" - -// Define COUNT_RESIDENT_BYTES_SUPPORTED if platform supports counting of the -// resident memory. -#if !defined(OS_NACL) -#define COUNT_RESIDENT_BYTES_SUPPORTED -#endif - -namespace base { - -class SharedMemory; -class UnguessableToken; - -namespace trace_event { - -class HeapProfilerSerializationState; -class TracedValue; - -// ProcessMemoryDump is as a strongly typed container which holds the dumps -// produced by the MemoryDumpProvider(s) for a specific process. -class BASE_EXPORT ProcessMemoryDump { - public: - struct BASE_EXPORT MemoryAllocatorDumpEdge { - bool operator==(const MemoryAllocatorDumpEdge&) const; - bool operator!=(const MemoryAllocatorDumpEdge&) const; - - MemoryAllocatorDumpGuid source; - MemoryAllocatorDumpGuid target; - int importance = 0; - bool overridable = false; - }; - - // Maps allocator dumps absolute names (allocator_name/heap/subheap) to - // MemoryAllocatorDump instances. - using AllocatorDumpsMap = - std::map<std::string, std::unique_ptr<MemoryAllocatorDump>>; - - using HeapDumpsMap = std::map<std::string, std::unique_ptr<TracedValue>>; - - // Stores allocator dump edges indexed by source allocator dump GUID. - using AllocatorDumpEdgesMap = - std::map<MemoryAllocatorDumpGuid, MemoryAllocatorDumpEdge>; - -#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) - // Returns the number of bytes in a kernel memory page. Some platforms may - // have a different value for kernel page sizes from user page sizes. It is - // important to use kernel memory page sizes for resident bytes calculation. - // In most cases, the two are the same. - static size_t GetSystemPageSize(); - - // Returns the total bytes resident for a virtual address range, with given - // |start_address| and |mapped_size|. |mapped_size| is specified in bytes. The - // value returned is valid only if the given range is currently mmapped by the - // process. The |start_address| must be page-aligned. - static size_t CountResidentBytes(void* start_address, size_t mapped_size); - - // The same as above, but the given mapped range should belong to the - // shared_memory's mapped region. - static base::Optional<size_t> CountResidentBytesInSharedMemory( - void* start_address, - size_t mapped_size); -#endif - - ProcessMemoryDump(scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state, - const MemoryDumpArgs& dump_args); - ProcessMemoryDump(ProcessMemoryDump&&); - ~ProcessMemoryDump(); - - ProcessMemoryDump& operator=(ProcessMemoryDump&&); - - // Creates a new MemoryAllocatorDump with the given name and returns the - // empty object back to the caller. - // Arguments: - // absolute_name: a name that uniquely identifies allocator dumps produced - // by this provider. It is possible to specify nesting by using a - // path-like string (e.g., v8/isolate1/heap1, v8/isolate1/heap2). - // Leading or trailing slashes are not allowed. - // guid: an optional identifier, unique among all processes within the - // scope of a global dump. This is only relevant when using - // AddOwnershipEdge() to express memory sharing. If omitted, - // it will be automatically generated. - // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps. - MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name); - MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name, - const MemoryAllocatorDumpGuid& guid); - - // Looks up a MemoryAllocatorDump given its allocator and heap names, or - // nullptr if not found. - MemoryAllocatorDump* GetAllocatorDump(const std::string& absolute_name) const; - - // Do NOT use this method. All dump providers should use - // CreateAllocatorDump(). Tries to create a new MemoryAllocatorDump only if it - // doesn't already exist. Creating multiple dumps with same name using - // GetOrCreateAllocatorDump() would override the existing scalars in MAD and - // cause misreporting. This method is used only in rare cases multiple - // components create allocator dumps with same name and only one of them adds - // size. - MemoryAllocatorDump* GetOrCreateAllocatorDump( - const std::string& absolute_name); - - // Creates a shared MemoryAllocatorDump, to express cross-process sharing. - // Shared allocator dumps are allowed to have duplicate guids within the - // global scope, in order to reference the same dump from multiple processes. - // See the design doc goo.gl/keU6Bf for reference usage patterns. - MemoryAllocatorDump* CreateSharedGlobalAllocatorDump( - const MemoryAllocatorDumpGuid& guid); - - // Creates a shared MemoryAllocatorDump as CreateSharedGlobalAllocatorDump, - // but with a WEAK flag. A weak dump will be discarded unless a non-weak dump - // is created using CreateSharedGlobalAllocatorDump by at least one process. - // The WEAK flag does not apply if a non-weak dump with the same GUID already - // exists or is created later. All owners and children of the discarded dump - // will also be discarded transitively. - MemoryAllocatorDump* CreateWeakSharedGlobalAllocatorDump( - const MemoryAllocatorDumpGuid& guid); - - // Looks up a shared MemoryAllocatorDump given its guid. - MemoryAllocatorDump* GetSharedGlobalAllocatorDump( - const MemoryAllocatorDumpGuid& guid) const; - - // Returns the map of the MemoryAllocatorDumps added to this dump. - const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; } - - AllocatorDumpsMap* mutable_allocator_dumps_for_serialization() const { - // Mojo takes a const input argument even for move-only types that can be - // mutate while serializing (like this one). Hence the const_cast. - return const_cast<AllocatorDumpsMap*>(&allocator_dumps_); - } - void SetAllocatorDumpsForSerialization( - std::vector<std::unique_ptr<MemoryAllocatorDump>>); - - // Only for mojo serialization. - std::vector<MemoryAllocatorDumpEdge> GetAllEdgesForSerialization() const; - void SetAllEdgesForSerialization(const std::vector<MemoryAllocatorDumpEdge>&); - - // Dumps heap usage with |allocator_name|. - void DumpHeapUsage( - const std::unordered_map<base::trace_event::AllocationContext, - base::trace_event::AllocationMetrics>& - metrics_by_context, - base::trace_event::TraceEventMemoryOverhead& overhead, - const char* allocator_name); - - // Adds an ownership relationship between two MemoryAllocatorDump(s) with the - // semantics: |source| owns |target|, and has the effect of attributing - // the memory usage of |target| to |source|. |importance| is optional and - // relevant only for the cases of co-ownership, where it acts as a z-index: - // the owner with the highest importance will be attributed |target|'s memory. - // If an edge is present, its importance will not be updated unless - // |importance| is larger. - void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, - const MemoryAllocatorDumpGuid& target, - int importance); - void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, - const MemoryAllocatorDumpGuid& target); - - // Adds edges that can be overriden by a later or earlier call to - // AddOwnershipEdge() with the same source and target with a different - // |importance| value. - void AddOverridableOwnershipEdge(const MemoryAllocatorDumpGuid& source, - const MemoryAllocatorDumpGuid& target, - int importance); - - // Creates ownership edges for memory backed by base::SharedMemory. Handles - // the case of cross process sharing and importnace of ownership for the case - // with and without the base::SharedMemory dump provider. The new version - // should just use global dumps created by SharedMemoryTracker and this - // function handles the transition until we get SharedMemory IDs through mojo - // channel crbug.com/713763. The weak version creates a weak global dump. - // |client_local_dump_guid| The guid of the local dump created by the client - // of base::SharedMemory. - // |shared_memory_guid| The ID of the base::SharedMemory that is assigned - // globally, used to create global dump edges in the new model. - // |importance| Importance of the global dump edges to say if the current - // process owns the memory segment. - void CreateSharedMemoryOwnershipEdge( - const MemoryAllocatorDumpGuid& client_local_dump_guid, - const UnguessableToken& shared_memory_guid, - int importance); - void CreateWeakSharedMemoryOwnershipEdge( - const MemoryAllocatorDumpGuid& client_local_dump_guid, - const UnguessableToken& shared_memory_guid, - int importance); - - const AllocatorDumpEdgesMap& allocator_dumps_edges() const { - return allocator_dumps_edges_; - } - - // Utility method to add a suballocation relationship with the following - // semantics: |source| is suballocated from |target_node_name|. - // This creates a child node of |target_node_name| and adds an ownership edge - // between |source| and the new child node. As a result, the UI will not - // account the memory of |source| in the target node. - void AddSuballocation(const MemoryAllocatorDumpGuid& source, - const std::string& target_node_name); - - const scoped_refptr<HeapProfilerSerializationState>& - heap_profiler_serialization_state() const { - return heap_profiler_serialization_state_; - } - - // Removes all the MemoryAllocatorDump(s) contained in this instance. This - // ProcessMemoryDump can be safely reused as if it was new once this returns. - void Clear(); - - // Merges all MemoryAllocatorDump(s) contained in |other| inside this - // ProcessMemoryDump, transferring their ownership to this instance. - // |other| will be an empty ProcessMemoryDump after this method returns. - // This is to allow dump providers to pre-populate ProcessMemoryDump instances - // and later move their contents into the ProcessMemoryDump passed as argument - // of the MemoryDumpProvider::OnMemoryDump(ProcessMemoryDump*) callback. - void TakeAllDumpsFrom(ProcessMemoryDump* other); - - // Populate the traced value with information about the memory allocator - // dumps. - void SerializeAllocatorDumpsInto(TracedValue* value) const; - - // Populate the traced value with information about the heap profiler. - void SerializeHeapProfilerDumpsInto(TracedValue* value) const; - - const HeapDumpsMap& heap_dumps() const { return heap_dumps_; } - - const MemoryDumpArgs& dump_args() const { return dump_args_; } - - private: - FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, BackgroundModeTest); - FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, SharedMemoryOwnershipTest); - FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, GuidsTest); - - MemoryAllocatorDump* AddAllocatorDumpInternal( - std::unique_ptr<MemoryAllocatorDump> mad); - - // A per-process token, valid throughout all the lifetime of the current - // process, used to disambiguate dumps with the same name generated in - // different processes. - const UnguessableToken& process_token() const { return process_token_; } - void set_process_token_for_testing(UnguessableToken token) { - process_token_ = token; - }; - - // Returns the Guid of the dump for the given |absolute_name| for - // for the given process' token. |process_token| is used to disambiguate GUIDs - // derived from the same name under different processes. - MemoryAllocatorDumpGuid GetDumpId(const std::string& absolute_name); - - void CreateSharedMemoryOwnershipEdgeInternal( - const MemoryAllocatorDumpGuid& client_local_dump_guid, - const UnguessableToken& shared_memory_guid, - int importance, - bool is_weak); - - MemoryAllocatorDump* GetBlackHoleMad(); - - UnguessableToken process_token_; - AllocatorDumpsMap allocator_dumps_; - HeapDumpsMap heap_dumps_; - - // State shared among all PMDs instances created in a given trace session. - scoped_refptr<HeapProfilerSerializationState> - heap_profiler_serialization_state_; - - // Keeps track of relationships between MemoryAllocatorDump(s). - AllocatorDumpEdgesMap allocator_dumps_edges_; - - // Level of detail of the current dump. - MemoryDumpArgs dump_args_; - - // This allocator dump is returned when an invalid dump is created in - // background mode. The attributes of the dump are ignored and not added to - // the trace. - std::unique_ptr<MemoryAllocatorDump> black_hole_mad_; - - // When set to true, the DCHECK(s) for invalid dump creations on the - // background mode are disabled for testing. - static bool is_black_hole_non_fatal_for_testing_; - - DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
diff --git a/base/trace_event/trace_buffer.cc b/base/trace_event/trace_buffer.cc deleted file mode 100644 index 8de470f..0000000 --- a/base/trace_event/trace_buffer.cc +++ /dev/null
@@ -1,347 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_buffer.h" - -#include <memory> -#include <utility> -#include <vector> - -#include "base/macros.h" -#include "base/trace_event/heap_profiler.h" -#include "base/trace_event/trace_event_impl.h" - -namespace base { -namespace trace_event { - -namespace { - -class TraceBufferRingBuffer : public TraceBuffer { - public: - TraceBufferRingBuffer(size_t max_chunks) - : max_chunks_(max_chunks), - recyclable_chunks_queue_(new size_t[queue_capacity()]), - queue_head_(0), - queue_tail_(max_chunks), - current_iteration_index_(0), - current_chunk_seq_(1) { - chunks_.reserve(max_chunks); - for (size_t i = 0; i < max_chunks; ++i) - recyclable_chunks_queue_[i] = i; - } - - std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override { - HEAP_PROFILER_SCOPED_IGNORE; - - // Because the number of threads is much less than the number of chunks, - // the queue should never be empty. - DCHECK(!QueueIsEmpty()); - - *index = recyclable_chunks_queue_[queue_head_]; - queue_head_ = NextQueueIndex(queue_head_); - current_iteration_index_ = queue_head_; - - if (*index >= chunks_.size()) - chunks_.resize(*index + 1); - - TraceBufferChunk* chunk = chunks_[*index].release(); - chunks_[*index] = nullptr; // Put nullptr in the slot of a in-flight chunk. - if (chunk) - chunk->Reset(current_chunk_seq_++); - else - chunk = new TraceBufferChunk(current_chunk_seq_++); - - return std::unique_ptr<TraceBufferChunk>(chunk); - } - - void ReturnChunk(size_t index, - std::unique_ptr<TraceBufferChunk> chunk) override { - // When this method is called, the queue should not be full because it - // can contain all chunks including the one to be returned. - DCHECK(!QueueIsFull()); - DCHECK(chunk); - DCHECK_LT(index, chunks_.size()); - DCHECK(!chunks_[index]); - chunks_[index] = std::move(chunk); - recyclable_chunks_queue_[queue_tail_] = index; - queue_tail_ = NextQueueIndex(queue_tail_); - } - - bool IsFull() const override { return false; } - - size_t Size() const override { - // This is approximate because not all of the chunks are full. - return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize; - } - - size_t Capacity() const override { - return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize; - } - - TraceEvent* GetEventByHandle(TraceEventHandle handle) override { - if (handle.chunk_index >= chunks_.size()) - return nullptr; - TraceBufferChunk* chunk = chunks_[handle.chunk_index].get(); - if (!chunk || chunk->seq() != handle.chunk_seq) - return nullptr; - return chunk->GetEventAt(handle.event_index); - } - - const TraceBufferChunk* NextChunk() override { - if (chunks_.empty()) - return nullptr; - - while (current_iteration_index_ != queue_tail_) { - size_t chunk_index = recyclable_chunks_queue_[current_iteration_index_]; - current_iteration_index_ = NextQueueIndex(current_iteration_index_); - if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. - continue; - DCHECK(chunks_[chunk_index]); - return chunks_[chunk_index].get(); - } - return nullptr; - } - - void EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) override { - overhead->Add(TraceEventMemoryOverhead::kTraceBuffer, sizeof(*this)); - for (size_t queue_index = queue_head_; queue_index != queue_tail_; - queue_index = NextQueueIndex(queue_index)) { - size_t chunk_index = recyclable_chunks_queue_[queue_index]; - if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. - continue; - chunks_[chunk_index]->EstimateTraceMemoryOverhead(overhead); - } - } - - private: - bool QueueIsEmpty() const { return queue_head_ == queue_tail_; } - - size_t QueueSize() const { - return queue_tail_ > queue_head_ - ? queue_tail_ - queue_head_ - : queue_tail_ + queue_capacity() - queue_head_; - } - - bool QueueIsFull() const { return QueueSize() == queue_capacity() - 1; } - - size_t queue_capacity() const { - // One extra space to help distinguish full state and empty state. - return max_chunks_ + 1; - } - - size_t NextQueueIndex(size_t index) const { - index++; - if (index >= queue_capacity()) - index = 0; - return index; - } - - size_t max_chunks_; - std::vector<std::unique_ptr<TraceBufferChunk>> chunks_; - - std::unique_ptr<size_t[]> recyclable_chunks_queue_; - size_t queue_head_; - size_t queue_tail_; - - size_t current_iteration_index_; - uint32_t current_chunk_seq_; - - DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer); -}; - -class TraceBufferVector : public TraceBuffer { - public: - TraceBufferVector(size_t max_chunks) - : in_flight_chunk_count_(0), - current_iteration_index_(0), - max_chunks_(max_chunks) { - chunks_.reserve(max_chunks_); - } - - std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override { - HEAP_PROFILER_SCOPED_IGNORE; - - // This function may be called when adding normal events or indirectly from - // AddMetadataEventsWhileLocked(). We can not DECHECK(!IsFull()) because we - // have to add the metadata events and flush thread-local buffers even if - // the buffer is full. - *index = chunks_.size(); - // Put nullptr in the slot of a in-flight chunk. - chunks_.push_back(nullptr); - ++in_flight_chunk_count_; - // + 1 because zero chunk_seq is not allowed. - return std::unique_ptr<TraceBufferChunk>( - new TraceBufferChunk(static_cast<uint32_t>(*index) + 1)); - } - - void ReturnChunk(size_t index, - std::unique_ptr<TraceBufferChunk> chunk) override { - DCHECK_GT(in_flight_chunk_count_, 0u); - DCHECK_LT(index, chunks_.size()); - DCHECK(!chunks_[index]); - --in_flight_chunk_count_; - chunks_[index] = std::move(chunk); - } - - bool IsFull() const override { return chunks_.size() >= max_chunks_; } - - size_t Size() const override { - // This is approximate because not all of the chunks are full. - return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize; - } - - size_t Capacity() const override { - return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize; - } - - TraceEvent* GetEventByHandle(TraceEventHandle handle) override { - if (handle.chunk_index >= chunks_.size()) - return nullptr; - TraceBufferChunk* chunk = chunks_[handle.chunk_index].get(); - if (!chunk || chunk->seq() != handle.chunk_seq) - return nullptr; - return chunk->GetEventAt(handle.event_index); - } - - const TraceBufferChunk* NextChunk() override { - while (current_iteration_index_ < chunks_.size()) { - // Skip in-flight chunks. - const TraceBufferChunk* chunk = chunks_[current_iteration_index_++].get(); - if (chunk) - return chunk; - } - return nullptr; - } - - void EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) override { - const size_t chunks_ptr_vector_allocated_size = - sizeof(*this) + max_chunks_ * sizeof(decltype(chunks_)::value_type); - const size_t chunks_ptr_vector_resident_size = - sizeof(*this) + chunks_.size() * sizeof(decltype(chunks_)::value_type); - overhead->Add(TraceEventMemoryOverhead::kTraceBuffer, - chunks_ptr_vector_allocated_size, - chunks_ptr_vector_resident_size); - for (size_t i = 0; i < chunks_.size(); ++i) { - TraceBufferChunk* chunk = chunks_[i].get(); - // Skip the in-flight (nullptr) chunks. They will be accounted by the - // per-thread-local dumpers, see ThreadLocalEventBuffer::OnMemoryDump. - if (chunk) - chunk->EstimateTraceMemoryOverhead(overhead); - } - } - - private: - size_t in_flight_chunk_count_; - size_t current_iteration_index_; - size_t max_chunks_; - std::vector<std::unique_ptr<TraceBufferChunk>> chunks_; - - DISALLOW_COPY_AND_ASSIGN(TraceBufferVector); -}; - -} // namespace - -TraceBufferChunk::TraceBufferChunk(uint32_t seq) : next_free_(0), seq_(seq) {} - -TraceBufferChunk::~TraceBufferChunk() = default; - -void TraceBufferChunk::Reset(uint32_t new_seq) { - for (size_t i = 0; i < next_free_; ++i) - chunk_[i].Reset(); - next_free_ = 0; - seq_ = new_seq; - cached_overhead_estimate_.reset(); -} - -TraceEvent* TraceBufferChunk::AddTraceEvent(size_t* event_index) { - DCHECK(!IsFull()); - *event_index = next_free_++; - return &chunk_[*event_index]; -} - -void TraceBufferChunk::EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) { - if (!cached_overhead_estimate_) { - cached_overhead_estimate_.reset(new TraceEventMemoryOverhead); - - // When estimating the size of TraceBufferChunk, exclude the array of trace - // events, as they are computed individually below. - cached_overhead_estimate_->Add(TraceEventMemoryOverhead::kTraceBufferChunk, - sizeof(*this) - sizeof(chunk_)); - } - - const size_t num_cached_estimated_events = - cached_overhead_estimate_->GetCount( - TraceEventMemoryOverhead::kTraceEvent); - DCHECK_LE(num_cached_estimated_events, size()); - - if (IsFull() && num_cached_estimated_events == size()) { - overhead->Update(*cached_overhead_estimate_); - return; - } - - for (size_t i = num_cached_estimated_events; i < size(); ++i) - chunk_[i].EstimateTraceMemoryOverhead(cached_overhead_estimate_.get()); - - if (IsFull()) { - cached_overhead_estimate_->AddSelf(); - } else { - // The unused TraceEvents in |chunks_| are not cached. They will keep - // changing as new TraceEvents are added to this chunk, so they are - // computed on the fly. - const size_t num_unused_trace_events = capacity() - size(); - overhead->Add(TraceEventMemoryOverhead::kUnusedTraceEvent, - num_unused_trace_events * sizeof(TraceEvent)); - } - - overhead->Update(*cached_overhead_estimate_); -} - -TraceResultBuffer::OutputCallback -TraceResultBuffer::SimpleOutput::GetCallback() { - return Bind(&SimpleOutput::Append, Unretained(this)); -} - -void TraceResultBuffer::SimpleOutput::Append( - const std::string& json_trace_output) { - json_output += json_trace_output; -} - -TraceResultBuffer::TraceResultBuffer() : append_comma_(false) {} - -TraceResultBuffer::~TraceResultBuffer() = default; - -void TraceResultBuffer::SetOutputCallback( - const OutputCallback& json_chunk_callback) { - output_callback_ = json_chunk_callback; -} - -void TraceResultBuffer::Start() { - append_comma_ = false; - output_callback_.Run("["); -} - -void TraceResultBuffer::AddFragment(const std::string& trace_fragment) { - if (append_comma_) - output_callback_.Run(","); - append_comma_ = true; - output_callback_.Run(trace_fragment); -} - -void TraceResultBuffer::Finish() { - output_callback_.Run("]"); -} - -TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(size_t max_chunks) { - return new TraceBufferRingBuffer(max_chunks); -} - -TraceBuffer* TraceBuffer::CreateTraceBufferVectorOfSize(size_t max_chunks) { - return new TraceBufferVector(max_chunks); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_buffer.h b/base/trace_event/trace_buffer.h deleted file mode 100644 index 3d6465f..0000000 --- a/base/trace_event/trace_buffer.h +++ /dev/null
@@ -1,130 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_BUFFER_H_ -#define BASE_TRACE_EVENT_TRACE_BUFFER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/base_export.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_impl.h" - -namespace base { - -namespace trace_event { - -// TraceBufferChunk is the basic unit of TraceBuffer. -class BASE_EXPORT TraceBufferChunk { - public: - explicit TraceBufferChunk(uint32_t seq); - ~TraceBufferChunk(); - - void Reset(uint32_t new_seq); - TraceEvent* AddTraceEvent(size_t* event_index); - bool IsFull() const { return next_free_ == kTraceBufferChunkSize; } - - uint32_t seq() const { return seq_; } - size_t capacity() const { return kTraceBufferChunkSize; } - size_t size() const { return next_free_; } - - TraceEvent* GetEventAt(size_t index) { - DCHECK(index < size()); - return &chunk_[index]; - } - const TraceEvent* GetEventAt(size_t index) const { - DCHECK(index < size()); - return &chunk_[index]; - } - - void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); - - // These values must be kept consistent with the numbers of bits of - // chunk_index and event_index fields in TraceEventHandle - // (in trace_event_impl.h). - static const size_t kMaxChunkIndex = (1u << 26) - 1; - static const size_t kTraceBufferChunkSize = 64; - - private: - size_t next_free_; - std::unique_ptr<TraceEventMemoryOverhead> cached_overhead_estimate_; - TraceEvent chunk_[kTraceBufferChunkSize]; - uint32_t seq_; -}; - -// TraceBuffer holds the events as they are collected. -class BASE_EXPORT TraceBuffer { - public: - virtual ~TraceBuffer() = default; - - virtual std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) = 0; - virtual void ReturnChunk(size_t index, - std::unique_ptr<TraceBufferChunk> chunk) = 0; - - virtual bool IsFull() const = 0; - virtual size_t Size() const = 0; - virtual size_t Capacity() const = 0; - virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) = 0; - - // For iteration. Each TraceBuffer can only be iterated once. - virtual const TraceBufferChunk* NextChunk() = 0; - - - // Computes an estimate of the size of the buffer, including all the retained - // objects. - virtual void EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) = 0; - - static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks); - static TraceBuffer* CreateTraceBufferVectorOfSize(size_t max_chunks); -}; - -// TraceResultBuffer collects and converts trace fragments returned by TraceLog -// to JSON output. -class BASE_EXPORT TraceResultBuffer { - public: - typedef base::Callback<void(const std::string&)> OutputCallback; - - // If you don't need to stream JSON chunks out efficiently, and just want to - // get a complete JSON string after calling Finish, use this struct to collect - // JSON trace output. - struct BASE_EXPORT SimpleOutput { - OutputCallback GetCallback(); - void Append(const std::string& json_string); - - // Do what you want with the json_output_ string after calling - // TraceResultBuffer::Finish. - std::string json_output; - }; - - TraceResultBuffer(); - ~TraceResultBuffer(); - - // Set callback. The callback will be called during Start with the initial - // JSON output and during AddFragment and Finish with following JSON output - // chunks. The callback target must live past the last calls to - // TraceResultBuffer::Start/AddFragment/Finish. - void SetOutputCallback(const OutputCallback& json_chunk_callback); - - // Start JSON output. This resets all internal state, so you can reuse - // the TraceResultBuffer by calling Start. - void Start(); - - // Call AddFragment 0 or more times to add trace fragments from TraceLog. - void AddFragment(const std::string& trace_fragment); - - // When all fragments have been added, call Finish to complete the JSON - // formatted output. - void Finish(); - - private: - OutputCallback output_callback_; - bool append_comma_; -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_BUFFER_H_
diff --git a/base/trace_event/trace_category.h b/base/trace_event/trace_category.h deleted file mode 100644 index 792bc5e..0000000 --- a/base/trace_event/trace_category.h +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_CATEGORY_H_ -#define BASE_TRACE_EVENT_TRACE_CATEGORY_H_ - -#include <stdint.h> - -namespace base { -namespace trace_event { - -// Captures the state of an invidivual trace category. Nothing except tracing -// internals (e.g., TraceLog) is supposed to have non-const Category pointers. -struct TraceCategory { - // The TRACE_EVENT macros should only use this value as a bool. - // These enum values are effectively a public API and third_party projects - // depend on their value. Hence, never remove or recycle existing bits, unless - // you are sure that all the third-party projects that depend on this have - // been updated. - enum StateFlags : uint8_t { - ENABLED_FOR_RECORDING = 1 << 0, - - // Not used anymore. - DEPRECATED_ENABLED_FOR_MONITORING = 1 << 1, - DEPRECATED_ENABLED_FOR_EVENT_CALLBACK = 1 << 2, - - ENABLED_FOR_ETW_EXPORT = 1 << 3, - ENABLED_FOR_FILTERING = 1 << 4 - }; - - static const TraceCategory* FromStatePtr(const uint8_t* state_ptr) { - static_assert( - offsetof(TraceCategory, state_) == 0, - "|state_| must be the first field of the TraceCategory class."); - return reinterpret_cast<const TraceCategory*>(state_ptr); - } - - bool is_valid() const { return name_ != nullptr; } - void set_name(const char* name) { name_ = name; } - const char* name() const { - DCHECK(is_valid()); - return name_; - } - - // TODO(primiano): This is an intermediate solution to deal with the fact that - // today TRACE_EVENT* macros cache the state ptr. They should just cache the - // full TraceCategory ptr, which is immutable, and use these helper function - // here. This will get rid of the need of this awkward ptr getter completely. - const uint8_t* state_ptr() const { - return const_cast<const uint8_t*>(&state_); - } - - uint8_t state() const { - return *const_cast<volatile const uint8_t*>(&state_); - } - - bool is_enabled() const { return state() != 0; } - - void set_state(uint8_t state) { - *const_cast<volatile uint8_t*>(&state_) = state; - } - - void clear_state_flag(StateFlags flag) { set_state(state() & (~flag)); } - void set_state_flag(StateFlags flag) { set_state(state() | flag); } - - uint32_t enabled_filters() const { - return *const_cast<volatile const uint32_t*>(&enabled_filters_); - } - - bool is_filter_enabled(size_t index) const { - DCHECK(index < sizeof(enabled_filters_) * 8); - return (enabled_filters() & (1 << index)) != 0; - } - - void set_enabled_filters(uint32_t enabled_filters) { - *const_cast<volatile uint32_t*>(&enabled_filters_) = enabled_filters; - } - - void reset_for_testing() { - set_state(0); - set_enabled_filters(0); - } - - // These fields should not be accessed directly, not even by tracing code. - // The only reason why these are not private is because it makes it impossible - // to have a global array of TraceCategory in category_registry.cc without - // creating initializers. See discussion on goo.gl/qhZN94 and - // crbug.com/{660967,660828}. - - // The enabled state. TRACE_EVENT* macros will capture events if any of the - // flags here are set. Since TRACE_EVENTx macros are used in a lot of - // fast-paths, accesses to this field are non-barriered and racy by design. - // This field is mutated when starting/stopping tracing and we don't care - // about missing some events. - uint8_t state_; - - // When ENABLED_FOR_FILTERING is set, this contains a bitmap to the - // corresponding filter (see event_filters.h). - uint32_t enabled_filters_; - - // TraceCategory group names are long lived static strings. - const char* name_; -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_CATEGORY_H_
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc deleted file mode 100644 index 624a29c..0000000 --- a/base/trace_event/trace_config.cc +++ /dev/null
@@ -1,557 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_config.h" - -#include <stddef.h> - -#include <utility> - -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/memory/ptr_util.h" -#include "base/strings/string_split.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/memory_dump_request_args.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace trace_event { - -namespace { - -// String options that can be used to initialize TraceOptions. -const char kRecordUntilFull[] = "record-until-full"; -const char kRecordContinuously[] = "record-continuously"; -const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible"; -const char kTraceToConsole[] = "trace-to-console"; -const char kEnableSystrace[] = "enable-systrace"; -const char kEnableArgumentFilter[] = "enable-argument-filter"; - -// String parameters that can be used to parse the trace config string. -const char kRecordModeParam[] = "record_mode"; -const char kEnableSystraceParam[] = "enable_systrace"; -const char kEnableArgumentFilterParam[] = "enable_argument_filter"; - -// String parameters that is used to parse memory dump config in trace config -// string. -const char kMemoryDumpConfigParam[] = "memory_dump_config"; -const char kAllowedDumpModesParam[] = "allowed_dump_modes"; -const char kTriggersParam[] = "triggers"; -const char kTriggerModeParam[] = "mode"; -const char kMinTimeBetweenDumps[] = "min_time_between_dumps_ms"; -const char kTriggerTypeParam[] = "type"; -const char kPeriodicIntervalLegacyParam[] = "periodic_interval_ms"; -const char kHeapProfilerOptions[] = "heap_profiler_options"; -const char kBreakdownThresholdBytes[] = "breakdown_threshold_bytes"; - -// String parameters used to parse category event filters. -const char kEventFiltersParam[] = "event_filters"; -const char kFilterPredicateParam[] = "filter_predicate"; -const char kFilterArgsParam[] = "filter_args"; - -class ConvertableTraceConfigToTraceFormat - : public base::trace_event::ConvertableToTraceFormat { - public: - explicit ConvertableTraceConfigToTraceFormat(const TraceConfig& trace_config) - : trace_config_(trace_config) {} - - ~ConvertableTraceConfigToTraceFormat() override = default; - - void AppendAsTraceFormat(std::string* out) const override { - out->append(trace_config_.ToString()); - } - - private: - const TraceConfig trace_config_; -}; - -std::set<MemoryDumpLevelOfDetail> GetDefaultAllowedMemoryDumpModes() { - std::set<MemoryDumpLevelOfDetail> all_modes; - for (uint32_t mode = static_cast<uint32_t>(MemoryDumpLevelOfDetail::FIRST); - mode <= static_cast<uint32_t>(MemoryDumpLevelOfDetail::LAST); mode++) { - all_modes.insert(static_cast<MemoryDumpLevelOfDetail>(mode)); - } - return all_modes; -} - -} // namespace - -TraceConfig::MemoryDumpConfig::HeapProfiler::HeapProfiler() - : breakdown_threshold_bytes(kDefaultBreakdownThresholdBytes) {} - -void TraceConfig::MemoryDumpConfig::HeapProfiler::Clear() { - breakdown_threshold_bytes = kDefaultBreakdownThresholdBytes; -} - -void TraceConfig::ResetMemoryDumpConfig( - const TraceConfig::MemoryDumpConfig& memory_dump_config) { - memory_dump_config_.Clear(); - memory_dump_config_ = memory_dump_config; -} - -TraceConfig::MemoryDumpConfig::MemoryDumpConfig() = default; - -TraceConfig::MemoryDumpConfig::MemoryDumpConfig( - const MemoryDumpConfig& other) = default; - -TraceConfig::MemoryDumpConfig::~MemoryDumpConfig() = default; - -void TraceConfig::MemoryDumpConfig::Clear() { - allowed_dump_modes.clear(); - triggers.clear(); - heap_profiler_options.Clear(); -} - -void TraceConfig::MemoryDumpConfig::Merge( - const TraceConfig::MemoryDumpConfig& config) { - triggers.insert(triggers.end(), config.triggers.begin(), - config.triggers.end()); - allowed_dump_modes.insert(config.allowed_dump_modes.begin(), - config.allowed_dump_modes.end()); - heap_profiler_options.breakdown_threshold_bytes = - std::min(heap_profiler_options.breakdown_threshold_bytes, - config.heap_profiler_options.breakdown_threshold_bytes); -} - -TraceConfig::EventFilterConfig::EventFilterConfig( - const std::string& predicate_name) - : predicate_name_(predicate_name) {} - -TraceConfig::EventFilterConfig::~EventFilterConfig() = default; - -TraceConfig::EventFilterConfig::EventFilterConfig(const EventFilterConfig& tc) { - *this = tc; -} - -TraceConfig::EventFilterConfig& TraceConfig::EventFilterConfig::operator=( - const TraceConfig::EventFilterConfig& rhs) { - if (this == &rhs) - return *this; - - predicate_name_ = rhs.predicate_name_; - category_filter_ = rhs.category_filter_; - - if (rhs.args_) - args_ = rhs.args_->CreateDeepCopy(); - - return *this; -} - -void TraceConfig::EventFilterConfig::InitializeFromConfigDict( - const base::DictionaryValue* event_filter) { - category_filter_.InitializeFromConfigDict(*event_filter); - - const base::DictionaryValue* args_dict = nullptr; - if (event_filter->GetDictionary(kFilterArgsParam, &args_dict)) - args_ = args_dict->CreateDeepCopy(); -} - -void TraceConfig::EventFilterConfig::SetCategoryFilter( - const TraceConfigCategoryFilter& category_filter) { - category_filter_ = category_filter; -} - -void TraceConfig::EventFilterConfig::ToDict( - DictionaryValue* filter_dict) const { - filter_dict->SetString(kFilterPredicateParam, predicate_name()); - - category_filter_.ToDict(filter_dict); - - if (args_) - filter_dict->Set(kFilterArgsParam, args_->CreateDeepCopy()); -} - -bool TraceConfig::EventFilterConfig::GetArgAsSet( - const char* key, - std::unordered_set<std::string>* out_set) const { - const ListValue* list = nullptr; - if (!args_->GetList(key, &list)) - return false; - for (size_t i = 0; i < list->GetSize(); ++i) { - std::string value; - if (list->GetString(i, &value)) - out_set->insert(value); - } - return true; -} - -bool TraceConfig::EventFilterConfig::IsCategoryGroupEnabled( - const StringPiece& category_group_name) const { - return category_filter_.IsCategoryGroupEnabled(category_group_name); -} - -// static -std::string TraceConfig::TraceRecordModeToStr(TraceRecordMode record_mode) { - switch (record_mode) { - case RECORD_UNTIL_FULL: - return kRecordUntilFull; - case RECORD_CONTINUOUSLY: - return kRecordContinuously; - case RECORD_AS_MUCH_AS_POSSIBLE: - return kRecordAsMuchAsPossible; - case ECHO_TO_CONSOLE: - return kTraceToConsole; - default: - NOTREACHED(); - } - return kRecordUntilFull; -} - -TraceConfig::TraceConfig() { - InitializeDefault(); -} - -TraceConfig::TraceConfig(StringPiece category_filter_string, - StringPiece trace_options_string) { - InitializeFromStrings(category_filter_string, trace_options_string); -} - -TraceConfig::TraceConfig(StringPiece category_filter_string, - TraceRecordMode record_mode) { - InitializeFromStrings(category_filter_string, - TraceConfig::TraceRecordModeToStr(record_mode)); -} - -TraceConfig::TraceConfig(const DictionaryValue& config) { - InitializeFromConfigDict(config); -} - -TraceConfig::TraceConfig(StringPiece config_string) { - if (!config_string.empty()) - InitializeFromConfigString(config_string); - else - InitializeDefault(); -} - -TraceConfig::TraceConfig(const TraceConfig& tc) = default; - -TraceConfig::~TraceConfig() = default; - -TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) { - if (this == &rhs) - return *this; - - record_mode_ = rhs.record_mode_; - enable_systrace_ = rhs.enable_systrace_; - enable_argument_filter_ = rhs.enable_argument_filter_; - category_filter_ = rhs.category_filter_; - memory_dump_config_ = rhs.memory_dump_config_; - event_filters_ = rhs.event_filters_; - return *this; -} - -std::string TraceConfig::ToString() const { - std::unique_ptr<DictionaryValue> dict = ToDict(); - std::string json; - JSONWriter::Write(*dict, &json); - return json; -} - -std::unique_ptr<ConvertableToTraceFormat> -TraceConfig::AsConvertableToTraceFormat() const { - return std::make_unique<ConvertableTraceConfigToTraceFormat>(*this); -} - -std::string TraceConfig::ToCategoryFilterString() const { - return category_filter_.ToFilterString(); -} - -bool TraceConfig::IsCategoryGroupEnabled( - const StringPiece& category_group_name) const { - // TraceLog should call this method only as part of enabling/disabling - // categories. - return category_filter_.IsCategoryGroupEnabled(category_group_name); -} - -void TraceConfig::Merge(const TraceConfig& config) { - if (record_mode_ != config.record_mode_ - || enable_systrace_ != config.enable_systrace_ - || enable_argument_filter_ != config.enable_argument_filter_) { - DLOG(ERROR) << "Attempting to merge trace config with a different " - << "set of options."; - } - - category_filter_.Merge(config.category_filter_); - - memory_dump_config_.Merge(config.memory_dump_config_); - - event_filters_.insert(event_filters_.end(), config.event_filters().begin(), - config.event_filters().end()); -} - -void TraceConfig::Clear() { - record_mode_ = RECORD_UNTIL_FULL; - enable_systrace_ = false; - enable_argument_filter_ = false; - category_filter_.Clear(); - memory_dump_config_.Clear(); - event_filters_.clear(); -} - -void TraceConfig::InitializeDefault() { - record_mode_ = RECORD_UNTIL_FULL; - enable_systrace_ = false; - enable_argument_filter_ = false; -} - -void TraceConfig::InitializeFromConfigDict(const DictionaryValue& dict) { - record_mode_ = RECORD_UNTIL_FULL; - std::string record_mode; - if (dict.GetString(kRecordModeParam, &record_mode)) { - if (record_mode == kRecordUntilFull) { - record_mode_ = RECORD_UNTIL_FULL; - } else if (record_mode == kRecordContinuously) { - record_mode_ = RECORD_CONTINUOUSLY; - } else if (record_mode == kTraceToConsole) { - record_mode_ = ECHO_TO_CONSOLE; - } else if (record_mode == kRecordAsMuchAsPossible) { - record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; - } - } - - bool val; - enable_systrace_ = dict.GetBoolean(kEnableSystraceParam, &val) ? val : false; - enable_argument_filter_ = - dict.GetBoolean(kEnableArgumentFilterParam, &val) ? val : false; - - category_filter_.InitializeFromConfigDict(dict); - - const base::ListValue* category_event_filters = nullptr; - if (dict.GetList(kEventFiltersParam, &category_event_filters)) - SetEventFiltersFromConfigList(*category_event_filters); - - if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { - // If dump triggers not set, the client is using the legacy with just - // category enabled. So, use the default periodic dump config. - const DictionaryValue* memory_dump_config = nullptr; - if (dict.GetDictionary(kMemoryDumpConfigParam, &memory_dump_config)) - SetMemoryDumpConfigFromConfigDict(*memory_dump_config); - else - SetDefaultMemoryDumpConfig(); - } -} - -void TraceConfig::InitializeFromConfigString(StringPiece config_string) { - auto dict = DictionaryValue::From(JSONReader::Read(config_string)); - if (dict) - InitializeFromConfigDict(*dict); - else - InitializeDefault(); -} - -void TraceConfig::InitializeFromStrings(StringPiece category_filter_string, - StringPiece trace_options_string) { - if (!category_filter_string.empty()) - category_filter_.InitializeFromString(category_filter_string); - - record_mode_ = RECORD_UNTIL_FULL; - enable_systrace_ = false; - enable_argument_filter_ = false; - if (!trace_options_string.empty()) { - std::vector<std::string> split = - SplitString(trace_options_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); - for (const std::string& token : split) { - if (token == kRecordUntilFull) { - record_mode_ = RECORD_UNTIL_FULL; - } else if (token == kRecordContinuously) { - record_mode_ = RECORD_CONTINUOUSLY; - } else if (token == kTraceToConsole) { - record_mode_ = ECHO_TO_CONSOLE; - } else if (token == kRecordAsMuchAsPossible) { - record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; - } else if (token == kEnableSystrace) { - enable_systrace_ = true; - } else if (token == kEnableArgumentFilter) { - enable_argument_filter_ = true; - } - } - } - - if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { - SetDefaultMemoryDumpConfig(); - } -} - -void TraceConfig::SetMemoryDumpConfigFromConfigDict( - const DictionaryValue& memory_dump_config) { - // Set allowed dump modes. - memory_dump_config_.allowed_dump_modes.clear(); - const ListValue* allowed_modes_list; - if (memory_dump_config.GetList(kAllowedDumpModesParam, &allowed_modes_list)) { - for (size_t i = 0; i < allowed_modes_list->GetSize(); ++i) { - std::string level_of_detail_str; - allowed_modes_list->GetString(i, &level_of_detail_str); - memory_dump_config_.allowed_dump_modes.insert( - StringToMemoryDumpLevelOfDetail(level_of_detail_str)); - } - } else { - // If allowed modes param is not given then allow all modes by default. - memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes(); - } - - // Set triggers - memory_dump_config_.triggers.clear(); - const ListValue* trigger_list = nullptr; - if (memory_dump_config.GetList(kTriggersParam, &trigger_list) && - trigger_list->GetSize() > 0) { - for (size_t i = 0; i < trigger_list->GetSize(); ++i) { - const DictionaryValue* trigger = nullptr; - if (!trigger_list->GetDictionary(i, &trigger)) - continue; - - MemoryDumpConfig::Trigger dump_config; - int interval = 0; - if (!trigger->GetInteger(kMinTimeBetweenDumps, &interval)) { - // If "min_time_between_dumps_ms" param was not given, then the trace - // config uses old format where only periodic dumps are supported. - trigger->GetInteger(kPeriodicIntervalLegacyParam, &interval); - dump_config.trigger_type = MemoryDumpType::PERIODIC_INTERVAL; - } else { - std::string trigger_type_str; - trigger->GetString(kTriggerTypeParam, &trigger_type_str); - dump_config.trigger_type = StringToMemoryDumpType(trigger_type_str); - } - DCHECK_GT(interval, 0); - dump_config.min_time_between_dumps_ms = static_cast<uint32_t>(interval); - - std::string level_of_detail_str; - trigger->GetString(kTriggerModeParam, &level_of_detail_str); - dump_config.level_of_detail = - StringToMemoryDumpLevelOfDetail(level_of_detail_str); - - memory_dump_config_.triggers.push_back(dump_config); - } - } - - // Set heap profiler options - const DictionaryValue* heap_profiler_options = nullptr; - if (memory_dump_config.GetDictionary(kHeapProfilerOptions, - &heap_profiler_options)) { - int min_size_bytes = 0; - if (heap_profiler_options->GetInteger(kBreakdownThresholdBytes, - &min_size_bytes) - && min_size_bytes >= 0) { - memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes = - static_cast<size_t>(min_size_bytes); - } else { - memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes = - MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes; - } - } -} - -void TraceConfig::SetDefaultMemoryDumpConfig() { - memory_dump_config_.Clear(); - memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes(); -} - -void TraceConfig::SetEventFiltersFromConfigList( - const base::ListValue& category_event_filters) { - event_filters_.clear(); - - for (size_t event_filter_index = 0; - event_filter_index < category_event_filters.GetSize(); - ++event_filter_index) { - const base::DictionaryValue* event_filter = nullptr; - if (!category_event_filters.GetDictionary(event_filter_index, - &event_filter)) - continue; - - std::string predicate_name; - CHECK(event_filter->GetString(kFilterPredicateParam, &predicate_name)) - << "Invalid predicate name in category event filter."; - - EventFilterConfig new_config(predicate_name); - new_config.InitializeFromConfigDict(event_filter); - event_filters_.push_back(new_config); - } -} - -std::unique_ptr<DictionaryValue> TraceConfig::ToDict() const { - auto dict = std::make_unique<DictionaryValue>(); - dict->SetString(kRecordModeParam, - TraceConfig::TraceRecordModeToStr(record_mode_)); - dict->SetBoolean(kEnableSystraceParam, enable_systrace_); - dict->SetBoolean(kEnableArgumentFilterParam, enable_argument_filter_); - - category_filter_.ToDict(dict.get()); - - if (!event_filters_.empty()) { - std::unique_ptr<base::ListValue> filter_list(new base::ListValue()); - for (const EventFilterConfig& filter : event_filters_) { - std::unique_ptr<base::DictionaryValue> filter_dict( - new base::DictionaryValue()); - filter.ToDict(filter_dict.get()); - filter_list->Append(std::move(filter_dict)); - } - dict->Set(kEventFiltersParam, std::move(filter_list)); - } - - if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { - auto allowed_modes = std::make_unique<ListValue>(); - for (auto dump_mode : memory_dump_config_.allowed_dump_modes) - allowed_modes->AppendString(MemoryDumpLevelOfDetailToString(dump_mode)); - - auto memory_dump_config = std::make_unique<DictionaryValue>(); - memory_dump_config->Set(kAllowedDumpModesParam, std::move(allowed_modes)); - - auto triggers_list = std::make_unique<ListValue>(); - for (const auto& config : memory_dump_config_.triggers) { - auto trigger_dict = std::make_unique<DictionaryValue>(); - trigger_dict->SetString(kTriggerTypeParam, - MemoryDumpTypeToString(config.trigger_type)); - trigger_dict->SetInteger( - kMinTimeBetweenDumps, - static_cast<int>(config.min_time_between_dumps_ms)); - trigger_dict->SetString( - kTriggerModeParam, - MemoryDumpLevelOfDetailToString(config.level_of_detail)); - triggers_list->Append(std::move(trigger_dict)); - } - - // Empty triggers will still be specified explicitly since it means that - // the periodic dumps are not enabled. - memory_dump_config->Set(kTriggersParam, std::move(triggers_list)); - - if (memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes != - MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes) { - auto options = std::make_unique<DictionaryValue>(); - options->SetInteger( - kBreakdownThresholdBytes, - memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes); - memory_dump_config->Set(kHeapProfilerOptions, std::move(options)); - } - dict->Set(kMemoryDumpConfigParam, std::move(memory_dump_config)); - } - return dict; -} - -std::string TraceConfig::ToTraceOptionsString() const { - std::string ret; - switch (record_mode_) { - case RECORD_UNTIL_FULL: - ret = kRecordUntilFull; - break; - case RECORD_CONTINUOUSLY: - ret = kRecordContinuously; - break; - case RECORD_AS_MUCH_AS_POSSIBLE: - ret = kRecordAsMuchAsPossible; - break; - case ECHO_TO_CONSOLE: - ret = kTraceToConsole; - break; - default: - NOTREACHED(); - } - if (enable_systrace_) - ret = ret + "," + kEnableSystrace; - if (enable_argument_filter_) - ret = ret + "," + kEnableArgumentFilter; - return ret; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_config.h b/base/trace_event/trace_config.h deleted file mode 100644 index decd54d..0000000 --- a/base/trace_event/trace_config.h +++ /dev/null
@@ -1,289 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_CONFIG_H_ -#define BASE_TRACE_EVENT_TRACE_CONFIG_H_ - -#include <stdint.h> - -#include <memory> -#include <set> -#include <string> -#include <unordered_set> -#include <vector> - -#include "base/base_export.h" -#include "base/gtest_prod_util.h" -#include "base/strings/string_piece.h" -#include "base/trace_event/memory_dump_request_args.h" -#include "base/trace_event/trace_config_category_filter.h" -#include "base/values.h" - -namespace base { -namespace trace_event { - -class ConvertableToTraceFormat; - -// Options determines how the trace buffer stores data. -// A Java counterpart will be generated for this enum. -// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base -enum TraceRecordMode { - // Record until the trace buffer is full. - RECORD_UNTIL_FULL, - - // Record until the user ends the trace. The trace buffer is a fixed size - // and we use it as a ring buffer during recording. - RECORD_CONTINUOUSLY, - - // Record until the trace buffer is full, but with a huge buffer size. - RECORD_AS_MUCH_AS_POSSIBLE, - - // Echo to console. Events are discarded. - ECHO_TO_CONSOLE, -}; - -class BASE_EXPORT TraceConfig { - public: - using StringList = std::vector<std::string>; - - // Specifies the memory dump config for tracing. - // Used only when "memory-infra" category is enabled. - struct BASE_EXPORT MemoryDumpConfig { - MemoryDumpConfig(); - MemoryDumpConfig(const MemoryDumpConfig& other); - ~MemoryDumpConfig(); - - // Specifies the triggers in the memory dump config. - struct Trigger { - uint32_t min_time_between_dumps_ms; - MemoryDumpLevelOfDetail level_of_detail; - MemoryDumpType trigger_type; - }; - - // Specifies the configuration options for the heap profiler. - struct HeapProfiler { - // Default value for |breakdown_threshold_bytes|. - enum { kDefaultBreakdownThresholdBytes = 1024 }; - - HeapProfiler(); - - // Reset the options to default. - void Clear(); - - uint32_t breakdown_threshold_bytes; - }; - - // Reset the values in the config. - void Clear(); - - void Merge(const MemoryDumpConfig& config); - - // Set of memory dump modes allowed for the tracing session. The explicitly - // triggered dumps will be successful only if the dump mode is allowed in - // the config. - std::set<MemoryDumpLevelOfDetail> allowed_dump_modes; - - std::vector<Trigger> triggers; - HeapProfiler heap_profiler_options; - }; - - class BASE_EXPORT EventFilterConfig { - public: - EventFilterConfig(const std::string& predicate_name); - EventFilterConfig(const EventFilterConfig& tc); - - ~EventFilterConfig(); - - EventFilterConfig& operator=(const EventFilterConfig& rhs); - - void InitializeFromConfigDict(const base::DictionaryValue* event_filter); - - void SetCategoryFilter(const TraceConfigCategoryFilter& category_filter); - - void ToDict(DictionaryValue* filter_dict) const; - - bool GetArgAsSet(const char* key, std::unordered_set<std::string>*) const; - - bool IsCategoryGroupEnabled(const StringPiece& category_group_name) const; - - const std::string& predicate_name() const { return predicate_name_; } - base::DictionaryValue* filter_args() const { return args_.get(); } - const TraceConfigCategoryFilter& category_filter() const { - return category_filter_; - } - - private: - std::string predicate_name_; - TraceConfigCategoryFilter category_filter_; - std::unique_ptr<base::DictionaryValue> args_; - }; - typedef std::vector<EventFilterConfig> EventFilters; - - static std::string TraceRecordModeToStr(TraceRecordMode record_mode); - - TraceConfig(); - - // Create TraceConfig object from category filter and trace options strings. - // - // |category_filter_string| is a comma-delimited list of category wildcards. - // A category can have an optional '-' prefix to make it an excluded category. - // All the same rules apply above, so for example, having both included and - // excluded categories in the same list would not be supported. - // - // |trace_options_string| is a comma-delimited list of trace options. - // Possible options are: "record-until-full", "record-continuously", - // "record-as-much-as-possible", "trace-to-console", "enable-systrace" and - // "enable-argument-filter". - // The first 4 options are trace recoding modes and hence - // mutually exclusive. If more than one trace recording modes appear in the - // options_string, the last one takes precedence. If none of the trace - // recording mode is specified, recording mode is RECORD_UNTIL_FULL. - // - // The trace option will first be reset to the default option - // (record_mode set to RECORD_UNTIL_FULL, enable_systrace and - // enable_argument_filter set to false) before options parsed from - // |trace_options_string| are applied on it. If |trace_options_string| is - // invalid, the final state of trace options is undefined. - // - // Example: TraceConfig("test_MyTest*", "record-until-full"); - // Example: TraceConfig("test_MyTest*,test_OtherStuff", - // "record-continuously"); - // Example: TraceConfig("-excluded_category1,-excluded_category2", - // "record-until-full, trace-to-console"); - // would set ECHO_TO_CONSOLE as the recording mode. - // Example: TraceConfig("-*,webkit", ""); - // would disable everything but webkit; and use default options. - // Example: TraceConfig("-webkit", ""); - // would enable everything but webkit; and use default options. - TraceConfig(StringPiece category_filter_string, - StringPiece trace_options_string); - - TraceConfig(StringPiece category_filter_string, TraceRecordMode record_mode); - - // Create TraceConfig object from the trace config string. - // - // |config_string| is a dictionary formatted as a JSON string, containing both - // category filters and trace options. - // - // Example: - // { - // "record_mode": "record-continuously", - // "enable_systrace": true, - // "enable_argument_filter": true, - // "included_categories": ["included", - // "inc_pattern*", - // "disabled-by-default-memory-infra"], - // "excluded_categories": ["excluded", "exc_pattern*"], - // "memory_dump_config": { - // "triggers": [ - // { - // "mode": "detailed", - // "periodic_interval_ms": 2000 - // } - // ] - // } - // } - // - // Note: memory_dump_config can be specified only if - // disabled-by-default-memory-infra category is enabled. - explicit TraceConfig(StringPiece config_string); - - // Functionally identical to the above, but takes a parsed dictionary as input - // instead of its JSON serialization. - explicit TraceConfig(const DictionaryValue& config); - - TraceConfig(const TraceConfig& tc); - - ~TraceConfig(); - - TraceConfig& operator=(const TraceConfig& rhs); - - TraceRecordMode GetTraceRecordMode() const { return record_mode_; } - bool IsSystraceEnabled() const { return enable_systrace_; } - bool IsArgumentFilterEnabled() const { return enable_argument_filter_; } - - void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; } - void EnableSystrace() { enable_systrace_ = true; } - void EnableArgumentFilter() { enable_argument_filter_ = true; } - - // Writes the string representation of the TraceConfig. The string is JSON - // formatted. - std::string ToString() const; - - // Returns a copy of the TraceConfig wrapped in a ConvertableToTraceFormat - std::unique_ptr<ConvertableToTraceFormat> AsConvertableToTraceFormat() const; - - // Write the string representation of the CategoryFilter part. - std::string ToCategoryFilterString() const; - - // Returns true if at least one category in the list is enabled by this - // trace config. This is used to determine if the category filters are - // enabled in the TRACE_* macros. - bool IsCategoryGroupEnabled(const StringPiece& category_group_name) const; - - // Merges config with the current TraceConfig - void Merge(const TraceConfig& config); - - void Clear(); - - // Clears and resets the memory dump config. - void ResetMemoryDumpConfig(const MemoryDumpConfig& memory_dump_config); - - const TraceConfigCategoryFilter& category_filter() const { - return category_filter_; - } - - const MemoryDumpConfig& memory_dump_config() const { - return memory_dump_config_; - } - - const EventFilters& event_filters() const { return event_filters_; } - void SetEventFilters(const EventFilters& filter_configs) { - event_filters_ = filter_configs; - } - - private: - FRIEND_TEST_ALL_PREFIXES(TraceConfigTest, TraceConfigFromValidLegacyFormat); - FRIEND_TEST_ALL_PREFIXES(TraceConfigTest, - TraceConfigFromInvalidLegacyStrings); - - // The default trace config, used when none is provided. - // Allows all non-disabled-by-default categories through, except if they end - // in the suffix 'Debug' or 'Test'. - void InitializeDefault(); - - // Initialize from a config dictionary. - void InitializeFromConfigDict(const DictionaryValue& dict); - - // Initialize from a config string. - void InitializeFromConfigString(StringPiece config_string); - - // Initialize from category filter and trace options strings - void InitializeFromStrings(StringPiece category_filter_string, - StringPiece trace_options_string); - - void SetMemoryDumpConfigFromConfigDict( - const DictionaryValue& memory_dump_config); - void SetDefaultMemoryDumpConfig(); - - void SetEventFiltersFromConfigList(const base::ListValue& event_filters); - std::unique_ptr<DictionaryValue> ToDict() const; - - std::string ToTraceOptionsString() const; - - TraceRecordMode record_mode_; - bool enable_systrace_ : 1; - bool enable_argument_filter_ : 1; - - TraceConfigCategoryFilter category_filter_; - - MemoryDumpConfig memory_dump_config_; - - EventFilters event_filters_; -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_CONFIG_H_
diff --git a/base/trace_event/trace_config_category_filter.cc b/base/trace_event/trace_config_category_filter.cc deleted file mode 100644 index d188430..0000000 --- a/base/trace_event/trace_config_category_filter.cc +++ /dev/null
@@ -1,235 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_config_category_filter.h" - -#include "base/memory/ptr_util.h" -#include "base/strings/pattern.h" -#include "base/strings/string_split.h" -#include "base/strings/string_tokenizer.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace trace_event { - -namespace { -const char kIncludedCategoriesParam[] = "included_categories"; -const char kExcludedCategoriesParam[] = "excluded_categories"; -} - -TraceConfigCategoryFilter::TraceConfigCategoryFilter() = default; - -TraceConfigCategoryFilter::TraceConfigCategoryFilter( - const TraceConfigCategoryFilter& other) = default; - -TraceConfigCategoryFilter::~TraceConfigCategoryFilter() = default; - -TraceConfigCategoryFilter& TraceConfigCategoryFilter::operator=( - const TraceConfigCategoryFilter& rhs) = default; - -void TraceConfigCategoryFilter::InitializeFromString( - const StringPiece& category_filter_string) { - std::vector<StringPiece> split = SplitStringPiece( - category_filter_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); - for (const StringPiece& category : split) { - // Ignore empty categories. - if (category.empty()) - continue; - if (category.front() == '-') { - // Excluded categories start with '-'. - // Remove '-' from category string. - excluded_categories_.push_back(category.substr(1).as_string()); - } else if (category.starts_with(TRACE_DISABLED_BY_DEFAULT(""))) { - disabled_categories_.push_back(category.as_string()); - } else { - included_categories_.push_back(category.as_string()); - } - } -} - -void TraceConfigCategoryFilter::InitializeFromConfigDict( - const DictionaryValue& dict) { - const ListValue* category_list = nullptr; - if (dict.GetList(kIncludedCategoriesParam, &category_list)) - SetCategoriesFromIncludedList(*category_list); - if (dict.GetList(kExcludedCategoriesParam, &category_list)) - SetCategoriesFromExcludedList(*category_list); -} - -bool TraceConfigCategoryFilter::IsCategoryGroupEnabled( - const StringPiece& category_group_name) const { - bool had_enabled_by_default = false; - DCHECK(!category_group_name.empty()); - CStringTokenizer category_group_tokens(category_group_name.begin(), - category_group_name.end(), ","); - while (category_group_tokens.GetNext()) { - StringPiece category_group_token = category_group_tokens.token_piece(); - // Don't allow empty tokens, nor tokens with leading or trailing space. - DCHECK(IsCategoryNameAllowed(category_group_token)) - << "Disallowed category string"; - if (IsCategoryEnabled(category_group_token)) - return true; - - if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*"))) - had_enabled_by_default = true; - } - // Do a second pass to check for explicitly disabled categories - // (those explicitly enabled have priority due to first pass). - category_group_tokens.Reset(); - bool category_group_disabled = false; - while (category_group_tokens.GetNext()) { - StringPiece category_group_token = category_group_tokens.token_piece(); - for (const std::string& category : excluded_categories_) { - if (MatchPattern(category_group_token, category)) { - // Current token of category_group_name is present in excluded_list. - // Flag the exclusion and proceed further to check if any of the - // remaining categories of category_group_name is not present in the - // excluded_ list. - category_group_disabled = true; - break; - } - // One of the category of category_group_name is not present in - // excluded_ list. So, if it's not a disabled-by-default category, - // it has to be included_ list. Enable the category_group_name - // for recording. - if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*"))) - category_group_disabled = false; - } - // One of the categories present in category_group_name is not present in - // excluded_ list. Implies this category_group_name group can be enabled - // for recording, since one of its groups is enabled for recording. - if (!category_group_disabled) - break; - } - // If the category group is not excluded, and there are no included patterns - // we consider this category group enabled, as long as it had categories - // other than disabled-by-default. - return !category_group_disabled && had_enabled_by_default && - included_categories_.empty(); -} - -bool TraceConfigCategoryFilter::IsCategoryEnabled( - const StringPiece& category_name) const { - // Check the disabled- filters and the disabled-* wildcard first so that a - // "*" filter does not include the disabled. - for (const std::string& category : disabled_categories_) { - if (MatchPattern(category_name, category)) - return true; - } - - if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) - return false; - - for (const std::string& category : included_categories_) { - if (MatchPattern(category_name, category)) - return true; - } - - return false; -} - -void TraceConfigCategoryFilter::Merge(const TraceConfigCategoryFilter& config) { - // Keep included patterns only if both filters have an included entry. - // Otherwise, one of the filter was specifying "*" and we want to honor the - // broadest filter. - if (!included_categories_.empty() && !config.included_categories_.empty()) { - included_categories_.insert(included_categories_.end(), - config.included_categories_.begin(), - config.included_categories_.end()); - } else { - included_categories_.clear(); - } - - disabled_categories_.insert(disabled_categories_.end(), - config.disabled_categories_.begin(), - config.disabled_categories_.end()); - excluded_categories_.insert(excluded_categories_.end(), - config.excluded_categories_.begin(), - config.excluded_categories_.end()); -} - -void TraceConfigCategoryFilter::Clear() { - included_categories_.clear(); - disabled_categories_.clear(); - excluded_categories_.clear(); -} - -void TraceConfigCategoryFilter::ToDict(DictionaryValue* dict) const { - StringList categories(included_categories_); - categories.insert(categories.end(), disabled_categories_.begin(), - disabled_categories_.end()); - AddCategoriesToDict(categories, kIncludedCategoriesParam, dict); - AddCategoriesToDict(excluded_categories_, kExcludedCategoriesParam, dict); -} - -std::string TraceConfigCategoryFilter::ToFilterString() const { - std::string filter_string; - WriteCategoryFilterString(included_categories_, &filter_string, true); - WriteCategoryFilterString(disabled_categories_, &filter_string, true); - WriteCategoryFilterString(excluded_categories_, &filter_string, false); - return filter_string; -} - -void TraceConfigCategoryFilter::SetCategoriesFromIncludedList( - const ListValue& included_list) { - included_categories_.clear(); - for (size_t i = 0; i < included_list.GetSize(); ++i) { - std::string category; - if (!included_list.GetString(i, &category)) - continue; - if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), - TRACE_DISABLED_BY_DEFAULT("")) == 0) { - disabled_categories_.push_back(category); - } else { - included_categories_.push_back(category); - } - } -} - -void TraceConfigCategoryFilter::SetCategoriesFromExcludedList( - const ListValue& excluded_list) { - excluded_categories_.clear(); - for (size_t i = 0; i < excluded_list.GetSize(); ++i) { - std::string category; - if (excluded_list.GetString(i, &category)) - excluded_categories_.push_back(category); - } -} - -void TraceConfigCategoryFilter::AddCategoriesToDict( - const StringList& categories, - const char* param, - DictionaryValue* dict) const { - if (categories.empty()) - return; - - auto list = std::make_unique<ListValue>(); - for (const std::string& category : categories) - list->AppendString(category); - dict->Set(param, std::move(list)); -} - -void TraceConfigCategoryFilter::WriteCategoryFilterString( - const StringList& values, - std::string* out, - bool included) const { - bool prepend_comma = !out->empty(); - int token_cnt = 0; - for (const std::string& category : values) { - if (token_cnt > 0 || prepend_comma) - StringAppendF(out, ","); - StringAppendF(out, "%s%s", (included ? "" : "-"), category.c_str()); - ++token_cnt; - } -} - -// static -bool TraceConfigCategoryFilter::IsCategoryNameAllowed(StringPiece str) { - return !str.empty() && str.front() != ' ' && str.back() != ' '; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_config_category_filter.h b/base/trace_event/trace_config_category_filter.h deleted file mode 100644 index 0140c1d..0000000 --- a/base/trace_event/trace_config_category_filter.h +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_CONFIG_CATEGORY_FILTER_H_ -#define BASE_TRACE_EVENT_TRACE_CONFIG_CATEGORY_FILTER_H_ - -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/strings/string_piece.h" -#include "base/values.h" - -namespace base { -namespace trace_event { - -// Configuration of categories enabled and disabled in TraceConfig. -class BASE_EXPORT TraceConfigCategoryFilter { - public: - using StringList = std::vector<std::string>; - - TraceConfigCategoryFilter(); - TraceConfigCategoryFilter(const TraceConfigCategoryFilter& other); - ~TraceConfigCategoryFilter(); - - TraceConfigCategoryFilter& operator=(const TraceConfigCategoryFilter& rhs); - - // Initializes from category filter string. See TraceConfig constructor for - // description of how to write category filter string. - void InitializeFromString(const StringPiece& category_filter_string); - - // Initializes TraceConfigCategoryFilter object from the config dictionary. - void InitializeFromConfigDict(const DictionaryValue& dict); - - // Merges this with category filter config. - void Merge(const TraceConfigCategoryFilter& config); - void Clear(); - - // Returns true if at least one category in the list is enabled by this - // trace config. This is used to determine if the category filters are - // enabled in the TRACE_* macros. - bool IsCategoryGroupEnabled(const StringPiece& category_group_name) const; - - // Returns true if the category is enabled according to this trace config. - // This tells whether a category is enabled from the TraceConfig's - // perspective. Please refer to IsCategoryGroupEnabled() to determine if a - // category is enabled from the tracing runtime's perspective. - bool IsCategoryEnabled(const StringPiece& category_name) const; - - void ToDict(DictionaryValue* dict) const; - - std::string ToFilterString() const; - - // Returns true if category name is a valid string. - static bool IsCategoryNameAllowed(StringPiece str); - - const StringList& included_categories() const { return included_categories_; } - const StringList& excluded_categories() const { return excluded_categories_; } - - private: - void SetCategoriesFromIncludedList(const ListValue& included_list); - void SetCategoriesFromExcludedList(const ListValue& excluded_list); - - void AddCategoriesToDict(const StringList& categories, - const char* param, - DictionaryValue* dict) const; - - void WriteCategoryFilterString(const StringList& values, - std::string* out, - bool included) const; - - StringList included_categories_; - StringList disabled_categories_; - StringList excluded_categories_; -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_CONFIG_CATEGORY_FILTER_H_
diff --git a/base/trace_event/trace_config_memory_test_util.h b/base/trace_event/trace_config_memory_test_util.h deleted file mode 100644 index 57608fd..0000000 --- a/base/trace_event/trace_config_memory_test_util.h +++ /dev/null
@@ -1,178 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_CONFIG_MEMORY_TEST_UTIL_H_ -#define BASE_TRACE_EVENT_TRACE_CONFIG_MEMORY_TEST_UTIL_H_ - -#include "base/strings/stringprintf.h" -#include "base/trace_event/memory_dump_manager.h" - -namespace base { -namespace trace_event { - -class TraceConfigMemoryTestUtil { - public: - static std::string GetTraceConfig_LegacyPeriodicTriggers(int light_period, - int heavy_period) { - return StringPrintf( - "{" - "\"enable_argument_filter\":false," - "\"enable_systrace\":false," - "\"excluded_categories\":[" - "\"*\"" - "]," - "\"included_categories\":[" - "\"%s\"" - "]," - "\"memory_dump_config\":{" - "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"]," - "\"heap_profiler_options\":{" - "\"breakdown_threshold_bytes\":2048" - "}," - "\"triggers\":[" - "{" - "\"mode\":\"light\"," - "\"periodic_interval_ms\":%d" - "}," - "{" - "\"mode\":\"detailed\"," - "\"periodic_interval_ms\":%d" - "}" - "]" - "}," - "\"record_mode\":\"record-until-full\"" - "}", - MemoryDumpManager::kTraceCategory, light_period, heavy_period); - ; - } - - static std::string GetTraceConfig_PeriodicTriggers(int light_period, - int heavy_period) { - return StringPrintf( - "{" - "\"enable_argument_filter\":false," - "\"enable_systrace\":false," - "\"excluded_categories\":[" - "\"*\"" - "]," - "\"included_categories\":[" - "\"%s\"" - "]," - "\"memory_dump_config\":{" - "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"]," - "\"heap_profiler_options\":{" - "\"breakdown_threshold_bytes\":2048" - "}," - "\"triggers\":[" - "{" - "\"min_time_between_dumps_ms\":%d," - "\"mode\":\"light\"," - "\"type\":\"periodic_interval\"" - "}," - "{" - "\"min_time_between_dumps_ms\":%d," - "\"mode\":\"detailed\"," - "\"type\":\"periodic_interval\"" - "}" - "]" - "}," - "\"record_mode\":\"record-until-full\"" - "}", - MemoryDumpManager::kTraceCategory, light_period, heavy_period); - } - - static std::string GetTraceConfig_EmptyTriggers() { - return StringPrintf( - "{" - "\"enable_argument_filter\":false," - "\"enable_systrace\":false," - "\"excluded_categories\":[" - "\"*\"" - "]," - "\"included_categories\":[" - "\"%s\"" - "]," - "\"memory_dump_config\":{" - "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"]," - "\"triggers\":[" - "]" - "}," - "\"record_mode\":\"record-until-full\"" - "}", - MemoryDumpManager::kTraceCategory); - } - - static std::string GetTraceConfig_NoTriggers() { - return StringPrintf( - "{" - "\"enable_argument_filter\":false," - "\"enable_systrace\":false," - "\"excluded_categories\":[" - "\"*\"" - "]," - "\"included_categories\":[" - "\"%s\"" - "]," - "\"record_mode\":\"record-until-full\"" - "}", - MemoryDumpManager::kTraceCategory); - } - - static std::string GetTraceConfig_BackgroundTrigger(int period_ms) { - return StringPrintf( - "{" - "\"enable_argument_filter\":false," - "\"enable_systrace\":false," - "\"excluded_categories\":[" - "\"*\"" - "]," - "\"included_categories\":[" - "\"%s\"" - "]," - "\"memory_dump_config\":{" - "\"allowed_dump_modes\":[\"background\"]," - "\"triggers\":[" - "{" - "\"min_time_between_dumps_ms\":%d," - "\"mode\":\"background\"," - "\"type\":\"periodic_interval\"" - "}" - "]" - "}," - "\"record_mode\":\"record-until-full\"" - "}", - MemoryDumpManager::kTraceCategory, period_ms); - } - - static std::string GetTraceConfig_PeakDetectionTrigger(int heavy_period) { - return StringPrintf( - "{" - "\"enable_argument_filter\":false," - "\"enable_systrace\":false," - "\"excluded_categories\":[" - "\"*\"" - "]," - "\"included_categories\":[" - "\"%s\"" - "]," - "\"memory_dump_config\":{" - "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"]," - "\"triggers\":[" - "{" - "\"min_time_between_dumps_ms\":%d," - "\"mode\":\"detailed\"," - "\"type\":\"peak_memory_usage\"" - "}" - "]" - "}," - "\"record_mode\":\"record-until-full\"" - "}", - MemoryDumpManager::kTraceCategory, heavy_period); - } -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_CONFIG_MEMORY_TEST_UTIL_H_
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h deleted file mode 100644 index e3ee400..0000000 --- a/base/trace_event/trace_event.h +++ /dev/null
@@ -1,1170 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_H_ - -// This header file defines implementation details of how the trace macros in -// trace_event_common.h collect and store trace events. Anything not -// implementation-specific should go in trace_event_common.h instead of here. - -#include <stddef.h> -#include <stdint.h> - -#include <string> - -#include "base/atomicops.h" -#include "base/macros.h" -#include "base/time/time.h" -#include "base/time/time_override.h" -#include "base/trace_event/common/trace_event_common.h" -#include "base/trace_event/heap_profiler.h" -#include "base/trace_event/trace_category.h" -#include "base/trace_event/trace_event_system_stats_monitor.h" -#include "base/trace_event/trace_log.h" -#include "build_config.h" - -// By default, const char* argument values are assumed to have long-lived scope -// and will not be copied. Use this macro to force a const char* to be copied. -#define TRACE_STR_COPY(str) \ - trace_event_internal::TraceStringWithCopy(str) - -// DEPRECATED: do not use: Consider using TRACE_ID_{GLOBAL, LOCAL} macros, -// instead. By default, uint64_t ID argument values are not mangled with the -// Process ID in TRACE_EVENT_ASYNC macros. Use this macro to force Process ID -// mangling. -#define TRACE_ID_MANGLE(id) \ - trace_event_internal::TraceID::ForceMangle(id) - -// DEPRECATED: do not use: Consider using TRACE_ID_{GLOBAL, LOCAL} macros, -// instead. By default, pointers are mangled with the Process ID in -// TRACE_EVENT_ASYNC macros. Use this macro to prevent Process ID mangling. -#define TRACE_ID_DONT_MANGLE(id) \ - trace_event_internal::TraceID::DontMangle(id) - -// By default, trace IDs are eventually converted to a single 64-bit number. Use -// this macro to add a scope string. For example, -// -// TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( -// "network", "ResourceLoad", -// TRACE_ID_WITH_SCOPE("BlinkResourceID", resourceID)); -// -// Also, it is possible to prepend the ID with another number, like the process -// ID. This is useful in creating IDs that are unique among all processes. To do -// that, pass two numbers after the scope string instead of one. For example, -// -// TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( -// "network", "ResourceLoad", -// TRACE_ID_WITH_SCOPE("BlinkResourceID", pid, resourceID)); -#define TRACE_ID_WITH_SCOPE(scope, ...) \ - trace_event_internal::TraceID::WithScope(scope, ##__VA_ARGS__) - -#define TRACE_ID_GLOBAL(id) trace_event_internal::TraceID::GlobalId(id) -#define TRACE_ID_LOCAL(id) trace_event_internal::TraceID::LocalId(id) - -#define TRACE_EVENT_API_CURRENT_THREAD_ID \ - static_cast<int>(base::PlatformThread::CurrentId()) - -#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ - UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \ - (base::trace_event::TraceCategory::ENABLED_FOR_RECORDING | \ - base::trace_event::TraceCategory::ENABLED_FOR_ETW_EXPORT)) - -#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED() \ - UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \ - (base::trace_event::TraceCategory::ENABLED_FOR_RECORDING | \ - base::trace_event::TraceCategory::ENABLED_FOR_ETW_EXPORT | \ - base::trace_event::TraceCategory::ENABLED_FOR_FILTERING)) - -//////////////////////////////////////////////////////////////////////////////// -// Implementation specific tracing API definitions. - -// Get a pointer to the enabled state of the given trace category. Only -// long-lived literal strings should be given as the category group. The -// returned pointer can be held permanently in a local static for example. If -// the unsigned char is non-zero, tracing is enabled. If tracing is enabled, -// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled -// between the load of the tracing state and the call to -// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out -// for best performance when tracing is disabled. -// const unsigned char* -// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group) -#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \ - base::trace_event::TraceLog::GetCategoryGroupEnabled - -// Get the number of times traces have been recorded. This is used to implement -// the TRACE_EVENT_IS_NEW_TRACE facility. -// unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED() -#define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \ - base::trace_event::TraceLog::GetInstance()->GetNumTracesRecorded - -// Add a trace event to the platform tracing system. -// base::trace_event::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT( -// char phase, -// const unsigned char* category_group_enabled, -// const char* name, -// const char* scope, -// unsigned long long id, -// int num_args, -// const char** arg_names, -// const unsigned char* arg_types, -// const unsigned long long* arg_values, -// std::unique_ptr<ConvertableToTraceFormat>* -// convertable_values, -// unsigned int flags) -#define TRACE_EVENT_API_ADD_TRACE_EVENT \ - base::trace_event::TraceLog::GetInstance()->AddTraceEvent - -// Add a trace event to the platform tracing system. -// base::trace_event::TraceEventHandle -// TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID( -// char phase, -// const unsigned char* category_group_enabled, -// const char* name, -// const char* scope, -// unsigned long long id, -// unsigned long long bind_id, -// int num_args, -// const char** arg_names, -// const unsigned char* arg_types, -// const unsigned long long* arg_values, -// std::unique_ptr<ConvertableToTraceFormat>* -// convertable_values, -// unsigned int flags) -#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID \ - base::trace_event::TraceLog::GetInstance()->AddTraceEventWithBindId - -// Add a trace event to the platform tracing system overriding the pid. -// The resulting event will have tid = pid == (process_id passed here). -// base::trace_event::TraceEventHandle -// TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( -// char phase, -// const unsigned char* category_group_enabled, -// const char* name, -// const char* scope, -// unsigned long long id, -// int process_id, -// int num_args, -// const char** arg_names, -// const unsigned char* arg_types, -// const unsigned long long* arg_values, -// std::unique_ptr<ConvertableToTraceFormat>* -// convertable_values, -// unsigned int flags) -#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID \ - base::trace_event::TraceLog::GetInstance()->AddTraceEventWithProcessId - -// Add a trace event to the platform tracing system. -// base::trace_event::TraceEventHandle -// TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( -// char phase, -// const unsigned char* category_group_enabled, -// const char* name, -// const char* scope, -// unsigned long long id, -// int thread_id, -// const TimeTicks& timestamp, -// int num_args, -// const char** arg_names, -// const unsigned char* arg_types, -// const unsigned long long* arg_values, -// std::unique_ptr<ConvertableToTraceFormat>* -// convertable_values, -// unsigned int flags) -#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \ - base::trace_event::TraceLog::GetInstance() \ - ->AddTraceEventWithThreadIdAndTimestamp - -// Set the duration field of a COMPLETE trace event. -// void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( -// const unsigned char* category_group_enabled, -// const char* name, -// base::trace_event::TraceEventHandle id) -#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \ - base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDuration - -// Set the duration field of a COMPLETE trace event. -// void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT( -// const unsigned char* category_group_enabled, -// const char* name, -// base::trace_event::TraceEventHandle id, -// const TimeTicks& now, -// const ThreadTicks* thread_now) -#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT \ - base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDurationExplicit - -// Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method -// on the convertable value will be called at flush time. -// TRACE_EVENT_API_ADD_METADATA_EVENT( -// const unsigned char* category_group_enabled, -// const char* event_name, -// const char* arg_name, -// std::unique_ptr<ConvertableToTraceFormat> arg_value) -#define TRACE_EVENT_API_ADD_METADATA_EVENT \ - trace_event_internal::AddMetadataEvent - -// Defines atomic operations used internally by the tracing system. -#define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord -#define TRACE_EVENT_API_ATOMIC_LOAD(var) base::subtle::NoBarrier_Load(&(var)) -#define TRACE_EVENT_API_ATOMIC_STORE(var, value) \ - base::subtle::NoBarrier_Store(&(var), (value)) - -// Defines visibility for classes in trace_event.h -#define TRACE_EVENT_API_CLASS_EXPORT BASE_EXPORT - -//////////////////////////////////////////////////////////////////////////////// - -// Implementation detail: trace event macros create temporary variables -// to keep instrumentation overhead low. These macros give each temporary -// variable a unique name based on the line number to prevent name collisions. -#define INTERNAL_TRACE_EVENT_UID3(a,b) \ - trace_event_unique_##a##b -#define INTERNAL_TRACE_EVENT_UID2(a,b) \ - INTERNAL_TRACE_EVENT_UID3(a,b) -#define INTERNAL_TRACE_EVENT_UID(name_prefix) \ - INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) - -// Implementation detail: internal macro to create static category. -// No barriers are needed, because this code is designed to operate safely -// even when the unsigned char* points to garbage data (which may be the case -// on processors without cache coherency). -#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \ - category_group, atomic, category_group_enabled) \ - category_group_enabled = \ - reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( \ - atomic)); \ - if (UNLIKELY(!category_group_enabled)) { \ - category_group_enabled = \ - TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \ - TRACE_EVENT_API_ATOMIC_STORE(atomic, \ - reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \ - category_group_enabled)); \ - } - -#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \ - static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \ - const unsigned char* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(category_group, \ - INTERNAL_TRACE_EVENT_UID(atomic), \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled)); - -// Implementation detail: internal macro to return unoverridden -// base::TimeTicks::Now(). This is important because in headless VirtualTime can -// override base:TimeTicks::Now(). -#define INTERNAL_TRACE_TIME_TICKS_NOW() \ - base::subtle::TimeTicksNowIgnoringOverride() - -// Implementation detail: internal macro to return unoverridden -// base::Time::Now(). This is important because in headless VirtualTime can -// override base:TimeTicks::Now(). -#define INTERNAL_TRACE_TIME_NOW() base::subtle::TimeNowIgnoringOverride() - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - trace_event_internal::AddTraceEvent( \ - phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \ - flags, trace_event_internal::kNoId, ##__VA_ARGS__); \ - } \ - } while (0) - -// Implementation detail: internal macro to create static category and add begin -// event if the category is enabled. Also adds the end event when the scope -// ends. -#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - base::trace_event::TraceEventHandle h = \ - trace_event_internal::AddTraceEvent( \ - TRACE_EVENT_PHASE_COMPLETE, \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \ - TRACE_EVENT_FLAG_NONE, trace_event_internal::kNoId, \ - ##__VA_ARGS__); \ - INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \ - } - -#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, \ - bind_id, flow_flags, ...) \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - trace_event_internal::TraceID trace_event_bind_id((bind_id)); \ - unsigned int trace_event_flags = \ - flow_flags | trace_event_bind_id.id_flags(); \ - base::trace_event::TraceEventHandle h = \ - trace_event_internal::AddTraceEvent( \ - TRACE_EVENT_PHASE_COMPLETE, \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \ - trace_event_flags, trace_event_bind_id.raw_id(), ##__VA_ARGS__); \ - INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \ - } - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \ - flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - trace_event_internal::TraceID trace_event_trace_id((id)); \ - unsigned int trace_event_flags = \ - flags | trace_event_trace_id.id_flags(); \ - trace_event_internal::AddTraceEvent( \ - phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \ - trace_event_flags, trace_event_internal::kNoId, ##__VA_ARGS__); \ - } \ - } while (0) - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \ - timestamp, flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \ - phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \ - TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, \ - flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, \ - trace_event_internal::kNoId, ##__VA_ARGS__); \ - } \ - } while (0) - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - phase, category_group, name, id, thread_id, timestamp, flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - trace_event_internal::TraceID trace_event_trace_id((id)); \ - unsigned int trace_event_flags = \ - flags | trace_event_trace_id.id_flags(); \ - trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \ - phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \ - thread_id, timestamp, \ - trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, \ - trace_event_internal::kNoId, ##__VA_ARGS__); \ - } \ - } while (0) - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMPS( \ - category_group, name, id, thread_id, begin_timestamp, end_timestamp, \ - thread_end_timestamp, flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - trace_event_internal::TraceID trace_event_trace_id((id)); \ - unsigned int trace_event_flags = \ - flags | trace_event_trace_id.id_flags(); \ - const unsigned char* uid_category_group_enabled = \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled); \ - auto handle = \ - trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \ - TRACE_EVENT_PHASE_COMPLETE, uid_category_group_enabled, name, \ - trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \ - thread_id, begin_timestamp, \ - trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, \ - trace_event_internal::kNoId, ##__VA_ARGS__); \ - TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT( \ - uid_category_group_enabled, name, handle, end_timestamp, \ - thread_end_timestamp); \ - } \ - } while (0) - -// The linked ID will not be mangled. -#define INTERNAL_TRACE_EVENT_ADD_LINK_IDS(category_group, name, id1, id2) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - trace_event_internal::TraceID source_id((id1)); \ - unsigned int source_flags = source_id.id_flags(); \ - trace_event_internal::TraceID target_id((id2)); \ - trace_event_internal::AddTraceEvent( \ - TRACE_EVENT_PHASE_LINK_IDS, \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - source_id.scope(), source_id.raw_id(), source_flags, \ - trace_event_internal::kNoId, "linked_id", \ - target_id.AsConvertableToTraceFormat()); \ - } \ - } while (0) - -// Implementation detail: internal macro to create static category and add -// metadata event if the category is enabled. -#define INTERNAL_TRACE_EVENT_METADATA_ADD(category_group, name, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ - TRACE_EVENT_API_ADD_METADATA_EVENT( \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - ##__VA_ARGS__); \ - } \ - } while (0) - -// Implementation detail: internal macro to enter and leave a -// context based on the current scope. -#define INTERNAL_TRACE_EVENT_SCOPED_CONTEXT(category_group, name, context) \ - struct INTERNAL_TRACE_EVENT_UID(ScopedContext) { \ - public: \ - INTERNAL_TRACE_EVENT_UID(ScopedContext)(uint64_t cid) : cid_(cid) { \ - TRACE_EVENT_ENTER_CONTEXT(category_group, name, cid_); \ - } \ - ~INTERNAL_TRACE_EVENT_UID(ScopedContext)() { \ - TRACE_EVENT_LEAVE_CONTEXT(category_group, name, cid_); \ - } \ - \ - private: \ - uint64_t cid_; \ - /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \ - INTERNAL_TRACE_EVENT_UID(ScopedContext) \ - (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {}; \ - void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {}; \ - }; \ - INTERNAL_TRACE_EVENT_UID(ScopedContext) \ - INTERNAL_TRACE_EVENT_UID(scoped_context)(context); - -// TODO(http://crbug.com760702) remove file name and just pass the program -// counter to the heap profiler macro. -// TODO(ssid): The program counter of the current task should be added here. -#define INTERNAL_TRACE_TASK_EXECUTION(run_function, task) \ - TRACE_EVENT1("toplevel", run_function, "src", (task).posted_from.ToString()) \ - TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION INTERNAL_TRACE_EVENT_UID( \ - task_event)((task).posted_from.file_name()); \ - TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER \ - INTERNAL_TRACE_EVENT_UID(task_pc_event)((task).posted_from.program_counter()); - -namespace trace_event_internal { - -// Specify these values when the corresponding argument of AddTraceEvent is not -// used. -const int kZeroNumArgs = 0; -const std::nullptr_t kGlobalScope = nullptr; -const unsigned long long kNoId = 0; - -// TraceID encapsulates an ID that can either be an integer or pointer. Pointers -// are by default mangled with the Process ID so that they are unlikely to -// collide when the same pointer is used on different processes. -class BASE_EXPORT TraceID { - public: - // Can be combined with WithScope. - class LocalId { - public: - explicit LocalId(const void* raw_id) - : raw_id_(static_cast<unsigned long long>( - reinterpret_cast<uintptr_t>(raw_id))) {} - explicit LocalId(unsigned long long raw_id) : raw_id_(raw_id) {} - unsigned long long raw_id() const { return raw_id_; } - private: - unsigned long long raw_id_; - }; - - // Can be combined with WithScope. - class GlobalId { - public: - explicit GlobalId(unsigned long long raw_id) : raw_id_(raw_id) {} - unsigned long long raw_id() const { return raw_id_; } - private: - unsigned long long raw_id_; - }; - - class WithScope { - public: - WithScope(const char* scope, unsigned long long raw_id) - : scope_(scope), raw_id_(raw_id) {} - WithScope(const char* scope, LocalId local_id) - : scope_(scope), raw_id_(local_id.raw_id()) { - id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID; - } - WithScope(const char* scope, GlobalId global_id) - : scope_(scope), raw_id_(global_id.raw_id()) { - id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID; - } - WithScope(const char* scope, - unsigned long long prefix, - unsigned long long raw_id) - : scope_(scope), has_prefix_(true), prefix_(prefix), raw_id_(raw_id) {} - WithScope(const char* scope, unsigned long long prefix, GlobalId global_id) - : scope_(scope), - has_prefix_(true), - prefix_(prefix), - raw_id_(global_id.raw_id()) { - id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID; - } - unsigned long long raw_id() const { return raw_id_; } - const char* scope() const { return scope_; } - bool has_prefix() const { return has_prefix_; } - unsigned long long prefix() const { return prefix_; } - unsigned int id_flags() const { return id_flags_; } - - private: - const char* scope_ = nullptr; - bool has_prefix_ = false; - unsigned long long prefix_; - unsigned long long raw_id_; - unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID; - }; - - // DEPRECATED: consider using LocalId or GlobalId, instead. - class DontMangle { - public: - explicit DontMangle(const void* raw_id) - : raw_id_(static_cast<unsigned long long>( - reinterpret_cast<uintptr_t>(raw_id))) {} - explicit DontMangle(unsigned long long raw_id) : raw_id_(raw_id) {} - explicit DontMangle(unsigned long raw_id) : raw_id_(raw_id) {} - explicit DontMangle(unsigned int raw_id) : raw_id_(raw_id) {} - explicit DontMangle(unsigned short raw_id) : raw_id_(raw_id) {} - explicit DontMangle(unsigned char raw_id) : raw_id_(raw_id) {} - explicit DontMangle(long long raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit DontMangle(long raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit DontMangle(int raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit DontMangle(short raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit DontMangle(signed char raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - unsigned long long raw_id() const { return raw_id_; } - private: - unsigned long long raw_id_; - }; - - // DEPRECATED: consider using LocalId or GlobalId, instead. - class ForceMangle { - public: - explicit ForceMangle(unsigned long long raw_id) : raw_id_(raw_id) {} - explicit ForceMangle(unsigned long raw_id) : raw_id_(raw_id) {} - explicit ForceMangle(unsigned int raw_id) : raw_id_(raw_id) {} - explicit ForceMangle(unsigned short raw_id) : raw_id_(raw_id) {} - explicit ForceMangle(unsigned char raw_id) : raw_id_(raw_id) {} - explicit ForceMangle(long long raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit ForceMangle(long raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit ForceMangle(int raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit ForceMangle(short raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - explicit ForceMangle(signed char raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - unsigned long long raw_id() const { return raw_id_; } - private: - unsigned long long raw_id_; - }; - - TraceID(const void* raw_id) : raw_id_(static_cast<unsigned long long>( - reinterpret_cast<uintptr_t>(raw_id))) { - id_flags_ = TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_MANGLE_ID; - } - TraceID(ForceMangle raw_id) : raw_id_(raw_id.raw_id()) { - id_flags_ = TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_MANGLE_ID; - } - TraceID(DontMangle raw_id) : raw_id_(raw_id.raw_id()) {} - TraceID(unsigned long long raw_id) : raw_id_(raw_id) {} - TraceID(unsigned long raw_id) : raw_id_(raw_id) {} - TraceID(unsigned int raw_id) : raw_id_(raw_id) {} - TraceID(unsigned short raw_id) : raw_id_(raw_id) {} - TraceID(unsigned char raw_id) : raw_id_(raw_id) {} - TraceID(long long raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - TraceID(long raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - TraceID(int raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - TraceID(short raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - TraceID(signed char raw_id) - : raw_id_(static_cast<unsigned long long>(raw_id)) {} - TraceID(LocalId raw_id) : raw_id_(raw_id.raw_id()) { - id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID; - } - TraceID(GlobalId raw_id) : raw_id_(raw_id.raw_id()) { - id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID; - } - TraceID(WithScope scoped_id) - : scope_(scoped_id.scope()), - has_prefix_(scoped_id.has_prefix()), - prefix_(scoped_id.prefix()), - raw_id_(scoped_id.raw_id()), - id_flags_(scoped_id.id_flags()) {} - - unsigned long long raw_id() const { return raw_id_; } - const char* scope() const { return scope_; } - bool has_prefix() const { return has_prefix_; } - unsigned long long prefix() const { return prefix_; } - unsigned int id_flags() const { return id_flags_; } - - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - AsConvertableToTraceFormat() const; - - private: - const char* scope_ = nullptr; - bool has_prefix_ = false; - unsigned long long prefix_; - unsigned long long raw_id_; - unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID; -}; - -// Simple union to store various types as unsigned long long. -union TraceValueUnion { - bool as_bool; - unsigned long long as_uint; - long long as_int; - double as_double; - const void* as_pointer; - const char* as_string; -}; - -// Simple container for const char* that should be copied instead of retained. -class TraceStringWithCopy { - public: - explicit TraceStringWithCopy(const char* str) : str_(str) {} - const char* str() const { return str_; } - private: - const char* str_; -}; - -// Define SetTraceValue for each allowed type. It stores the type and -// value in the return arguments. This allows this API to avoid declaring any -// structures so that it is portable to third_party libraries. -#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ - arg_expression, \ - union_member, \ - value_type_id) \ - static inline void SetTraceValue( \ - actual_type arg, \ - unsigned char* type, \ - unsigned long long* value) { \ - TraceValueUnion type_value; \ - type_value.union_member = arg_expression; \ - *type = value_type_id; \ - *value = type_value.as_uint; \ - } -// Simpler form for int types that can be safely casted. -#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ - value_type_id) \ - static inline void SetTraceValue( \ - actual_type arg, \ - unsigned char* type, \ - unsigned long long* value) { \ - *type = value_type_id; \ - *value = static_cast<unsigned long long>(arg); \ - } - -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL) -INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double, - TRACE_VALUE_TYPE_DOUBLE) -INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer, - TRACE_VALUE_TYPE_POINTER) -INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string, - TRACE_VALUE_TYPE_STRING) -INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(), - as_string, TRACE_VALUE_TYPE_COPY_STRING) - -#undef INTERNAL_DECLARE_SET_TRACE_VALUE -#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT - -// std::string version of SetTraceValue so that trace arguments can be strings. -static inline void SetTraceValue(const std::string& arg, - unsigned char* type, - unsigned long long* value) { - TraceValueUnion type_value; - type_value.as_string = arg.c_str(); - *type = TRACE_VALUE_TYPE_COPY_STRING; - *value = type_value.as_uint; -} - -// base::Time, base::TimeTicks, etc. versions of SetTraceValue to make it easier -// to trace these types. -static inline void SetTraceValue(const base::Time arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - -static inline void SetTraceValue(const base::TimeTicks arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - -static inline void SetTraceValue(const base::ThreadTicks arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - -// These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template -// functions are defined here instead of in the macro, because the arg_values -// could be temporary objects, such as std::string. In order to store -// pointers to the internal c_str and pass through to the tracing API, -// the arg_values must live throughout these procedures. - -template <class ARG1_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) { - const int num_args = 1; - unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE }; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[1] = {std::move(arg1_val)}; - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, &arg1_name, arg_types, NULL, convertable_values, - flags); -} - -template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[2] = {nullptr, std::move(arg2_val)}; - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, arg_values, convertable_values, - flags); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE; - arg_values[0] = 0; - SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[2] = {std::move(arg1_val), nullptr}; - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, arg_values, convertable_values, - flags); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - unsigned char arg_types[2] = - { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE }; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[2] = {std::move(arg1_val), std::move(arg2_val)}; - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, NULL, convertable_values, - flags); -} - -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id) { - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, kZeroNumArgs, NULL, NULL, NULL, NULL, flags); -} - -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id) { - const int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - const base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id); -} - -template<class ARG1_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val) { - const int num_args = 1; - unsigned char arg_types[1]; - unsigned long long arg_values[1]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, &arg1_name, arg_types, arg_values, NULL, flags); -} - -template<class ARG1_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, arg1_val); -} - -template <class ARG1_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::move(arg1_val)); -} - -template<class ARG1_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, arg_values, NULL, flags); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::move(arg1_val), arg2_name, arg2_val); -} - -template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, arg1_val, arg2_name, std::move(arg2_val)); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::move(arg1_val), arg2_name, std::move(arg2_val)); -} - -template<class ARG1_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, arg1_val, arg2_name, arg2_val); -} - -template <class ARG1_CONVERTABLE_TYPE> -static inline void AddMetadataEvent( - const unsigned char* category_group_enabled, - const char* event_name, - const char* arg_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg_value) { - const char* arg_names[1] = {arg_name}; - unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE}; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[1] = {std::move(arg_value)}; - base::trace_event::TraceLog::GetInstance()->AddMetadataEvent( - category_group_enabled, event_name, - 1, // num_args - arg_names, arg_types, - nullptr, // arg_values - convertable_values, TRACE_EVENT_FLAG_NONE); -} - -template <class ARG1_TYPE> -static void AddMetadataEvent(const unsigned char* category_group_enabled, - const char* event_name, - const char* arg_name, - const ARG1_TYPE& arg_val) { - const int num_args = 1; - const char* arg_names[1] = {arg_name}; - unsigned char arg_types[1]; - unsigned long long arg_values[1]; - SetTraceValue(arg_val, &arg_types[0], &arg_values[0]); - - base::trace_event::TraceLog::GetInstance()->AddMetadataEvent( - category_group_enabled, event_name, num_args, arg_names, arg_types, - arg_values, nullptr, TRACE_EVENT_FLAG_NONE); -} - -// Used by TRACE_EVENTx macros. Do not use directly. -class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { - public: - // Note: members of data_ intentionally left uninitialized. See Initialize. - ScopedTracer() : p_data_(NULL) {} - - ~ScopedTracer() { - if (p_data_ && *data_.category_group_enabled) { - TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( - data_.category_group_enabled, data_.name, data_.event_handle); - } - } - - void Initialize(const unsigned char* category_group_enabled, - const char* name, - base::trace_event::TraceEventHandle event_handle) { - data_.category_group_enabled = category_group_enabled; - data_.name = name; - data_.event_handle = event_handle; - p_data_ = &data_; - } - - private: - // This Data struct workaround is to avoid initializing all the members - // in Data during construction of this object, since this object is always - // constructed, even when tracing is disabled. If the members of Data were - // members of this class instead, compiler warnings occur about potential - // uninitialized accesses. - struct Data { - const unsigned char* category_group_enabled; - const char* name; - base::trace_event::TraceEventHandle event_handle; - }; - Data* p_data_; - Data data_; -}; - -// Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly. -class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient { - public: - ScopedTraceBinaryEfficient(const char* category_group, const char* name); - ~ScopedTraceBinaryEfficient(); - - private: - const unsigned char* category_group_enabled_; - const char* name_; - base::trace_event::TraceEventHandle event_handle_; -}; - -// This macro generates less code then TRACE_EVENT0 but is also -// slower to execute when tracing is off. It should generally only be -// used with code that is seldom executed or conditionally executed -// when debugging. -// For now the category_group must be "gpu". -#define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \ - trace_event_internal::ScopedTraceBinaryEfficient \ - INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name); - -} // namespace trace_event_internal - -namespace base { -namespace trace_event { - -template<typename IDType> class TraceScopedTrackableObject { - public: - TraceScopedTrackableObject(const char* category_group, const char* name, - IDType id) - : category_group_(category_group), - name_(name), - id_(id) { - TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group_, name_, id_); - } - - template <typename ArgType> void snapshot(ArgType snapshot) { - TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group_, name_, id_, snapshot); - } - - ~TraceScopedTrackableObject() { - TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group_, name_, id_); - } - - private: - const char* category_group_; - const char* name_; - IDType id_; - - DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_H_
diff --git a/base/trace_event/trace_event_android.cc b/base/trace_event/trace_event_android.cc deleted file mode 100644 index 30d9c74..0000000 --- a/base/trace_event/trace_event_android.cc +++ /dev/null
@@ -1,216 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_event_impl.h" - -#include <fcntl.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/format_macros.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/strings/stringprintf.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace trace_event { - -namespace { - -int g_atrace_fd = -1; -const char kATraceMarkerFile[] = "/sys/kernel/debug/tracing/trace_marker"; - -void WriteToATrace(int fd, const char* buffer, size_t size) { - size_t total_written = 0; - while (total_written < size) { - ssize_t written = HANDLE_EINTR(write( - fd, buffer + total_written, size - total_written)); - if (written <= 0) - break; - total_written += written; - } - if (total_written < size) { - PLOG(WARNING) << "Failed to write buffer '" << std::string(buffer, size) - << "' to " << kATraceMarkerFile; - } -} - -void WriteEvent( - char phase, - const char* category_group, - const char* name, - unsigned long long id, - const char** arg_names, - const unsigned char* arg_types, - const TraceEvent::TraceValue* arg_values, - const std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name); - if (flags & TRACE_EVENT_FLAG_HAS_ID) - StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id)); - out += '|'; - - for (int i = 0; i < kTraceMaxNumArgs && arg_names[i]; - ++i) { - if (i) - out += ';'; - out += arg_names[i]; - out += '='; - std::string::size_type value_start = out.length(); - if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values[i]->AppendAsTraceFormat(&out); - else - TraceEvent::AppendValueAsJSON(arg_types[i], arg_values[i], &out); - - // Remove the quotes which may confuse the atrace script. - ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'"); - ReplaceSubstringsAfterOffset(&out, value_start, "\"", ""); - // Replace chars used for separators with similar chars in the value. - std::replace(out.begin() + value_start, out.end(), ';', ','); - std::replace(out.begin() + value_start, out.end(), '|', '!'); - } - - out += '|'; - out += category_group; - WriteToATrace(g_atrace_fd, out.c_str(), out.size()); -} - -void NoOpOutputCallback(WaitableEvent* complete_event, - const scoped_refptr<RefCountedString>&, - bool has_more_events) { - if (!has_more_events) - complete_event->Signal(); -} - -void EndChromeTracing(TraceLog* trace_log, - WaitableEvent* complete_event) { - trace_log->SetDisabled(); - // Delete the buffered trace events as they have been sent to atrace. - trace_log->Flush(Bind(&NoOpOutputCallback, complete_event)); -} - -} // namespace - -// These functions support Android systrace.py when 'webview' category is -// traced. With the new adb_profile_chrome, we may have two phases: -// - before WebView is ready for combined tracing, we can use adb_profile_chrome -// to trace android categories other than 'webview' and chromium categories. -// In this way we can avoid the conflict between StartATrace/StopATrace and -// the intents. -// - TODO(wangxianzhu): after WebView is ready for combined tracing, remove -// StartATrace, StopATrace and SendToATrace, and perhaps send Java traces -// directly to atrace in trace_event_binding.cc. - -void TraceLog::StartATrace() { - if (g_atrace_fd != -1) - return; - - g_atrace_fd = HANDLE_EINTR(open(kATraceMarkerFile, O_WRONLY)); - if (g_atrace_fd == -1) { - PLOG(WARNING) << "Couldn't open " << kATraceMarkerFile; - return; - } - TraceConfig trace_config; - trace_config.SetTraceRecordMode(RECORD_CONTINUOUSLY); - SetEnabled(trace_config, TraceLog::RECORDING_MODE); -} - -void TraceLog::StopATrace() { - if (g_atrace_fd == -1) - return; - - close(g_atrace_fd); - g_atrace_fd = -1; - - // TraceLog::Flush() requires the current thread to have a message loop, but - // this thread called from Java may not have one, so flush in another thread. - Thread end_chrome_tracing_thread("end_chrome_tracing"); - WaitableEvent complete_event(WaitableEvent::ResetPolicy::AUTOMATIC, - WaitableEvent::InitialState::NOT_SIGNALED); - end_chrome_tracing_thread.Start(); - end_chrome_tracing_thread.task_runner()->PostTask( - FROM_HERE, base::Bind(&EndChromeTracing, Unretained(this), - Unretained(&complete_event))); - complete_event.Wait(); -} - -void TraceEvent::SendToATrace() { - if (g_atrace_fd == -1) - return; - - const char* category_group = - TraceLog::GetCategoryGroupName(category_group_enabled_); - - switch (phase_) { - case TRACE_EVENT_PHASE_BEGIN: - WriteEvent('B', category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); - break; - - case TRACE_EVENT_PHASE_COMPLETE: - WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E', - category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); - break; - - case TRACE_EVENT_PHASE_END: - // Though a single 'E' is enough, here append pid, name and - // category_group etc. So that unpaired events can be found easily. - WriteEvent('E', category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); - break; - - case TRACE_EVENT_PHASE_INSTANT: - // Simulate an instance event with a pair of begin/end events. - WriteEvent('B', category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); - WriteToATrace(g_atrace_fd, "E", 1); - break; - - case TRACE_EVENT_PHASE_COUNTER: - for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { - DCHECK(arg_types_[i] == TRACE_VALUE_TYPE_INT); - std::string out = base::StringPrintf( - "C|%d|%s-%s", getpid(), name_, arg_names_[i]); - if (flags_ & TRACE_EVENT_FLAG_HAS_ID) - StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id_)); - StringAppendF(&out, "|%d|%s", - static_cast<int>(arg_values_[i].as_int), category_group); - WriteToATrace(g_atrace_fd, out.c_str(), out.size()); - } - break; - - default: - // Do nothing. - break; - } -} - -void TraceLog::AddClockSyncMetadataEvent() { - int atrace_fd = HANDLE_EINTR(open(kATraceMarkerFile, O_WRONLY | O_APPEND)); - if (atrace_fd == -1) { - PLOG(WARNING) << "Couldn't open " << kATraceMarkerFile; - return; - } - - // Android's kernel trace system has a trace_marker feature: this is a file on - // debugfs that takes the written data and pushes it onto the trace - // buffer. So, to establish clock sync, we write our monotonic clock into that - // trace buffer. - double now_in_seconds = (TRACE_TIME_TICKS_NOW() - TimeTicks()).InSecondsF(); - std::string marker = StringPrintf( - "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds); - WriteToATrace(atrace_fd, marker.c_str(), marker.size()); - close(atrace_fd); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_event_argument.cc b/base/trace_event/trace_event_argument.cc deleted file mode 100644 index e614b27..0000000 --- a/base/trace_event/trace_event_argument.cc +++ /dev/null
@@ -1,576 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_event_argument.h" - -#include <stdint.h> - -#include <utility> - -#include "base/bits.h" -#include "base/containers/circular_deque.h" -#include "base/json/string_escape.h" -#include "base/memory/ptr_util.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_impl.h" -#include "base/trace_event/trace_event_memory_overhead.h" -#include "base/values.h" - -namespace base { -namespace trace_event { - -namespace { -const char kTypeStartDict = '{'; -const char kTypeEndDict = '}'; -const char kTypeStartArray = '['; -const char kTypeEndArray = ']'; -const char kTypeBool = 'b'; -const char kTypeInt = 'i'; -const char kTypeDouble = 'd'; -const char kTypeString = 's'; -const char kTypeCStr = '*'; // only used for key names - -#ifndef NDEBUG -const bool kStackTypeDict = false; -const bool kStackTypeArray = true; -#define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back()) -#define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size()) -#define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x) -#define DEBUG_POP_CONTAINER() nesting_stack_.pop_back() -#else -#define DCHECK_CURRENT_CONTAINER_IS(x) do {} while (0) -#define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) do {} while (0) -#define DEBUG_PUSH_CONTAINER(x) do {} while (0) -#define DEBUG_POP_CONTAINER() do {} while (0) -#endif - -inline void WriteKeyNameAsRawPtr(Pickle& pickle, const char* ptr) { - pickle.WriteBytes(&kTypeCStr, 1); - pickle.WriteUInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr))); -} - -inline void WriteKeyNameWithCopy(Pickle& pickle, base::StringPiece str) { - pickle.WriteBytes(&kTypeString, 1); - pickle.WriteString(str); -} - -std::string ReadKeyName(PickleIterator& pickle_iterator) { - const char* type = nullptr; - bool res = pickle_iterator.ReadBytes(&type, 1); - std::string key_name; - if (res && *type == kTypeCStr) { - uint64_t ptr_value = 0; - res = pickle_iterator.ReadUInt64(&ptr_value); - key_name = reinterpret_cast<const char*>(static_cast<uintptr_t>(ptr_value)); - } else if (res && *type == kTypeString) { - res = pickle_iterator.ReadString(&key_name); - } - DCHECK(res); - return key_name; -} -} // namespace - -TracedValue::TracedValue() : TracedValue(0) { -} - -TracedValue::TracedValue(size_t capacity) { - DEBUG_PUSH_CONTAINER(kStackTypeDict); - if (capacity) - pickle_.Reserve(capacity); -} - -TracedValue::~TracedValue() { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - DEBUG_POP_CONTAINER(); - DCHECK_CONTAINER_STACK_DEPTH_EQ(0u); -} - -void TracedValue::SetInteger(const char* name, int value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeInt, 1); - pickle_.WriteInt(value); - WriteKeyNameAsRawPtr(pickle_, name); -} - -void TracedValue::SetIntegerWithCopiedName(base::StringPiece name, int value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeInt, 1); - pickle_.WriteInt(value); - WriteKeyNameWithCopy(pickle_, name); -} - -void TracedValue::SetDouble(const char* name, double value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeDouble, 1); - pickle_.WriteDouble(value); - WriteKeyNameAsRawPtr(pickle_, name); -} - -void TracedValue::SetDoubleWithCopiedName(base::StringPiece name, - double value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeDouble, 1); - pickle_.WriteDouble(value); - WriteKeyNameWithCopy(pickle_, name); -} - -void TracedValue::SetBoolean(const char* name, bool value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeBool, 1); - pickle_.WriteBool(value); - WriteKeyNameAsRawPtr(pickle_, name); -} - -void TracedValue::SetBooleanWithCopiedName(base::StringPiece name, - bool value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeBool, 1); - pickle_.WriteBool(value); - WriteKeyNameWithCopy(pickle_, name); -} - -void TracedValue::SetString(const char* name, base::StringPiece value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeString, 1); - pickle_.WriteString(value); - WriteKeyNameAsRawPtr(pickle_, name); -} - -void TracedValue::SetStringWithCopiedName(base::StringPiece name, - base::StringPiece value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - pickle_.WriteBytes(&kTypeString, 1); - pickle_.WriteString(value); - WriteKeyNameWithCopy(pickle_, name); -} - -void TracedValue::SetValue(const char* name, const TracedValue& value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - BeginDictionary(name); - pickle_.WriteBytes(value.pickle_.payload(), - static_cast<int>(value.pickle_.payload_size())); - EndDictionary(); -} - -void TracedValue::SetValueWithCopiedName(base::StringPiece name, - const TracedValue& value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - BeginDictionaryWithCopiedName(name); - pickle_.WriteBytes(value.pickle_.payload(), - static_cast<int>(value.pickle_.payload_size())); - EndDictionary(); -} - -void TracedValue::BeginDictionary(const char* name) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - DEBUG_PUSH_CONTAINER(kStackTypeDict); - pickle_.WriteBytes(&kTypeStartDict, 1); - WriteKeyNameAsRawPtr(pickle_, name); -} - -void TracedValue::BeginDictionaryWithCopiedName(base::StringPiece name) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - DEBUG_PUSH_CONTAINER(kStackTypeDict); - pickle_.WriteBytes(&kTypeStartDict, 1); - WriteKeyNameWithCopy(pickle_, name); -} - -void TracedValue::BeginArray(const char* name) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - DEBUG_PUSH_CONTAINER(kStackTypeArray); - pickle_.WriteBytes(&kTypeStartArray, 1); - WriteKeyNameAsRawPtr(pickle_, name); -} - -void TracedValue::BeginArrayWithCopiedName(base::StringPiece name) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - DEBUG_PUSH_CONTAINER(kStackTypeArray); - pickle_.WriteBytes(&kTypeStartArray, 1); - WriteKeyNameWithCopy(pickle_, name); -} - -void TracedValue::EndDictionary() { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - DEBUG_POP_CONTAINER(); - pickle_.WriteBytes(&kTypeEndDict, 1); -} - -void TracedValue::AppendInteger(int value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - pickle_.WriteBytes(&kTypeInt, 1); - pickle_.WriteInt(value); -} - -void TracedValue::AppendDouble(double value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - pickle_.WriteBytes(&kTypeDouble, 1); - pickle_.WriteDouble(value); -} - -void TracedValue::AppendBoolean(bool value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - pickle_.WriteBytes(&kTypeBool, 1); - pickle_.WriteBool(value); -} - -void TracedValue::AppendString(base::StringPiece value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - pickle_.WriteBytes(&kTypeString, 1); - pickle_.WriteString(value); -} - -void TracedValue::BeginArray() { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - DEBUG_PUSH_CONTAINER(kStackTypeArray); - pickle_.WriteBytes(&kTypeStartArray, 1); -} - -void TracedValue::BeginDictionary() { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - DEBUG_PUSH_CONTAINER(kStackTypeDict); - pickle_.WriteBytes(&kTypeStartDict, 1); -} - -void TracedValue::EndArray() { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - DEBUG_POP_CONTAINER(); - pickle_.WriteBytes(&kTypeEndArray, 1); -} - -void TracedValue::SetValue(const char* name, - std::unique_ptr<base::Value> value) { - SetBaseValueWithCopiedName(name, *value); -} - -void TracedValue::SetBaseValueWithCopiedName(base::StringPiece name, - const base::Value& value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - switch (value.type()) { - case base::Value::Type::NONE: - case base::Value::Type::BINARY: - NOTREACHED(); - break; - - case base::Value::Type::BOOLEAN: { - bool bool_value; - value.GetAsBoolean(&bool_value); - SetBooleanWithCopiedName(name, bool_value); - } break; - - case base::Value::Type::INTEGER: { - int int_value; - value.GetAsInteger(&int_value); - SetIntegerWithCopiedName(name, int_value); - } break; - - case base::Value::Type::DOUBLE: { - double double_value; - value.GetAsDouble(&double_value); - SetDoubleWithCopiedName(name, double_value); - } break; - - case base::Value::Type::STRING: { - const Value* string_value; - value.GetAsString(&string_value); - SetStringWithCopiedName(name, string_value->GetString()); - } break; - - case base::Value::Type::DICTIONARY: { - const DictionaryValue* dict_value; - value.GetAsDictionary(&dict_value); - BeginDictionaryWithCopiedName(name); - for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd(); - it.Advance()) { - SetBaseValueWithCopiedName(it.key(), it.value()); - } - EndDictionary(); - } break; - - case base::Value::Type::LIST: { - const ListValue* list_value; - value.GetAsList(&list_value); - BeginArrayWithCopiedName(name); - for (const auto& base_value : *list_value) - AppendBaseValue(base_value); - EndArray(); - } break; - } -} - -void TracedValue::AppendBaseValue(const base::Value& value) { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); - switch (value.type()) { - case base::Value::Type::NONE: - case base::Value::Type::BINARY: - NOTREACHED(); - break; - - case base::Value::Type::BOOLEAN: { - bool bool_value; - value.GetAsBoolean(&bool_value); - AppendBoolean(bool_value); - } break; - - case base::Value::Type::INTEGER: { - int int_value; - value.GetAsInteger(&int_value); - AppendInteger(int_value); - } break; - - case base::Value::Type::DOUBLE: { - double double_value; - value.GetAsDouble(&double_value); - AppendDouble(double_value); - } break; - - case base::Value::Type::STRING: { - const Value* string_value; - value.GetAsString(&string_value); - AppendString(string_value->GetString()); - } break; - - case base::Value::Type::DICTIONARY: { - const DictionaryValue* dict_value; - value.GetAsDictionary(&dict_value); - BeginDictionary(); - for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd(); - it.Advance()) { - SetBaseValueWithCopiedName(it.key(), it.value()); - } - EndDictionary(); - } break; - - case base::Value::Type::LIST: { - const ListValue* list_value; - value.GetAsList(&list_value); - BeginArray(); - for (const auto& base_value : *list_value) - AppendBaseValue(base_value); - EndArray(); - } break; - } -} - -std::unique_ptr<base::Value> TracedValue::ToBaseValue() const { - base::Value root(base::Value::Type::DICTIONARY); - Value* cur_dict = &root; - Value* cur_list = nullptr; - std::vector<Value*> stack; - PickleIterator it(pickle_); - const char* type; - - while (it.ReadBytes(&type, 1)) { - DCHECK((cur_dict && !cur_list) || (cur_list && !cur_dict)); - switch (*type) { - case kTypeStartDict: { - base::Value new_dict(base::Value::Type::DICTIONARY); - if (cur_dict) { - stack.push_back(cur_dict); - cur_dict = cur_dict->SetKey(ReadKeyName(it), std::move(new_dict)); - } else { - cur_list->GetList().push_back(std::move(new_dict)); - // |new_dict| is invalidated at this point, so |cur_dict| needs to be - // reset. - cur_dict = &cur_list->GetList().back(); - stack.push_back(cur_list); - cur_list = nullptr; - } - } break; - - case kTypeEndArray: - case kTypeEndDict: { - if (stack.back()->is_dict()) { - cur_dict = stack.back(); - cur_list = nullptr; - } else if (stack.back()->is_list()) { - cur_list = stack.back(); - cur_dict = nullptr; - } - stack.pop_back(); - } break; - - case kTypeStartArray: { - base::Value new_list(base::Value::Type::LIST); - if (cur_dict) { - stack.push_back(cur_dict); - cur_list = cur_dict->SetKey(ReadKeyName(it), std::move(new_list)); - cur_dict = nullptr; - } else { - cur_list->GetList().push_back(std::move(new_list)); - stack.push_back(cur_list); - // |cur_list| is invalidated at this point by the Append, so it needs - // to be reset. - cur_list = &cur_list->GetList().back(); - } - } break; - - case kTypeBool: { - bool value; - CHECK(it.ReadBool(&value)); - base::Value new_bool(value); - if (cur_dict) { - cur_dict->SetKey(ReadKeyName(it), std::move(new_bool)); - } else { - cur_list->GetList().push_back(std::move(new_bool)); - } - } break; - - case kTypeInt: { - int value; - CHECK(it.ReadInt(&value)); - base::Value new_int(value); - if (cur_dict) { - cur_dict->SetKey(ReadKeyName(it), std::move(new_int)); - } else { - cur_list->GetList().push_back(std::move(new_int)); - } - } break; - - case kTypeDouble: { - double value; - CHECK(it.ReadDouble(&value)); - base::Value new_double(value); - if (cur_dict) { - cur_dict->SetKey(ReadKeyName(it), std::move(new_double)); - } else { - cur_list->GetList().push_back(std::move(new_double)); - } - } break; - - case kTypeString: { - std::string value; - CHECK(it.ReadString(&value)); - base::Value new_str(std::move(value)); - if (cur_dict) { - cur_dict->SetKey(ReadKeyName(it), std::move(new_str)); - } else { - cur_list->GetList().push_back(std::move(new_str)); - } - } break; - - default: - NOTREACHED(); - } - } - DCHECK(stack.empty()); - return base::Value::ToUniquePtrValue(std::move(root)); -} - -void TracedValue::AppendAsTraceFormat(std::string* out) const { - DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); - DCHECK_CONTAINER_STACK_DEPTH_EQ(1u); - - struct State { - enum Type { kTypeDict, kTypeArray }; - Type type; - bool needs_comma; - }; - - auto maybe_append_key_name = [](State current_state, PickleIterator* it, - std::string* out) { - if (current_state.type == State::kTypeDict) { - EscapeJSONString(ReadKeyName(*it), true, out); - out->append(":"); - } - }; - - base::circular_deque<State> state_stack; - - out->append("{"); - state_stack.push_back({State::kTypeDict}); - - PickleIterator it(pickle_); - for (const char* type; it.ReadBytes(&type, 1);) { - switch (*type) { - case kTypeEndDict: - out->append("}"); - state_stack.pop_back(); - continue; - - case kTypeEndArray: - out->append("]"); - state_stack.pop_back(); - continue; - } - - // Use an index so it will stay valid across resizes. - size_t current_state_index = state_stack.size() - 1; - if (state_stack[current_state_index].needs_comma) - out->append(","); - - switch (*type) { - case kTypeStartDict: { - maybe_append_key_name(state_stack[current_state_index], &it, out); - out->append("{"); - state_stack.push_back({State::kTypeDict}); - break; - } - - case kTypeStartArray: { - maybe_append_key_name(state_stack[current_state_index], &it, out); - out->append("["); - state_stack.push_back({State::kTypeArray}); - break; - } - - case kTypeBool: { - TraceEvent::TraceValue json_value; - CHECK(it.ReadBool(&json_value.as_bool)); - maybe_append_key_name(state_stack[current_state_index], &it, out); - TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out); - break; - } - - case kTypeInt: { - int value; - CHECK(it.ReadInt(&value)); - maybe_append_key_name(state_stack[current_state_index], &it, out); - TraceEvent::TraceValue json_value; - json_value.as_int = value; - TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out); - break; - } - - case kTypeDouble: { - TraceEvent::TraceValue json_value; - CHECK(it.ReadDouble(&json_value.as_double)); - maybe_append_key_name(state_stack[current_state_index], &it, out); - TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value, out); - break; - } - - case kTypeString: { - std::string value; - CHECK(it.ReadString(&value)); - maybe_append_key_name(state_stack[current_state_index], &it, out); - TraceEvent::TraceValue json_value; - json_value.as_string = value.c_str(); - TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value, out); - break; - } - - default: - NOTREACHED(); - } - - state_stack[current_state_index].needs_comma = true; - } - - out->append("}"); - state_stack.pop_back(); - - DCHECK(state_stack.empty()); -} - -void TracedValue::EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) { - overhead->Add(TraceEventMemoryOverhead::kTracedValue, - /* allocated size */ - pickle_.GetTotalAllocatedSize(), - /* resident size */ - pickle_.size()); -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h deleted file mode 100644 index 81d8c01..0000000 --- a/base/trace_event/trace_event_argument.h +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_ - -#include <stddef.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/macros.h" -#include "base/pickle.h" -#include "base/strings/string_piece.h" -#include "base/trace_event/trace_event_impl.h" - -namespace base { - -class Value; - -namespace trace_event { - -class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { - public: - TracedValue(); - explicit TracedValue(size_t capacity); - ~TracedValue() override; - - void EndDictionary(); - void EndArray(); - - // These methods assume that |name| is a long lived "quoted" string. - void SetInteger(const char* name, int value); - void SetDouble(const char* name, double value); - void SetBoolean(const char* name, bool value); - void SetString(const char* name, base::StringPiece value); - void SetValue(const char* name, const TracedValue& value); - void BeginDictionary(const char* name); - void BeginArray(const char* name); - - // These, instead, can be safely passed a temporary string. - void SetIntegerWithCopiedName(base::StringPiece name, int value); - void SetDoubleWithCopiedName(base::StringPiece name, double value); - void SetBooleanWithCopiedName(base::StringPiece name, bool value); - void SetStringWithCopiedName(base::StringPiece name, - base::StringPiece value); - void SetValueWithCopiedName(base::StringPiece name, - const TracedValue& value); - void BeginDictionaryWithCopiedName(base::StringPiece name); - void BeginArrayWithCopiedName(base::StringPiece name); - - void AppendInteger(int); - void AppendDouble(double); - void AppendBoolean(bool); - void AppendString(base::StringPiece); - void BeginArray(); - void BeginDictionary(); - - // ConvertableToTraceFormat implementation. - void AppendAsTraceFormat(std::string* out) const override; - - void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override; - - // DEPRECATED: do not use, here only for legacy reasons. These methods causes - // a copy-and-translation of the base::Value into the equivalent TracedValue. - // TODO(primiano): migrate the (three) existing clients to the cheaper - // SetValue(TracedValue) API. crbug.com/495628. - void SetValue(const char* name, std::unique_ptr<base::Value> value); - void SetBaseValueWithCopiedName(base::StringPiece name, - const base::Value& value); - void AppendBaseValue(const base::Value& value); - - // Public for tests only. - std::unique_ptr<base::Value> ToBaseValue() const; - - private: - Pickle pickle_; - -#ifndef NDEBUG - // In debug builds checks the pairings of {Start,End}{Dictionary,Array} - std::vector<bool> nesting_stack_; -#endif - - DISALLOW_COPY_AND_ASSIGN(TracedValue); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
diff --git a/base/trace_event/trace_event_filter.cc b/base/trace_event/trace_event_filter.cc deleted file mode 100644 index d0b116e..0000000 --- a/base/trace_event/trace_event_filter.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_event_filter.h" - -namespace base { -namespace trace_event { - -TraceEventFilter::TraceEventFilter() = default; -TraceEventFilter::~TraceEventFilter() = default; - -void TraceEventFilter::EndEvent(const char* category_name, - const char* event_name) const {} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_event_filter.h b/base/trace_event/trace_event_filter.h deleted file mode 100644 index 48c6711..0000000 --- a/base/trace_event/trace_event_filter.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_FILTER_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_FILTER_H_ - -#include <memory> - -#include "base/base_export.h" -#include "base/macros.h" - -namespace base { -namespace trace_event { - -class TraceEvent; - -// TraceEventFilter is like iptables for TRACE_EVENT macros. Filters can be -// enabled on a per-category basis, hence a single filter instance can serve -// more than a TraceCategory. There are two use cases for filters: -// 1. Snooping TRACE_EVENT macros without adding them to the TraceLog. This is -// possible by setting the ENABLED_FOR_FILTERING flag on a category w/o -// ENABLED_FOR_RECORDING (see TraceConfig for user-facing configuration). -// 2. Filtering TRACE_EVENT macros before they are added to the TraceLog. This -// requires both the ENABLED_FOR_FILTERING and ENABLED_FOR_RECORDING flags -// on the category. -// More importantly, filters must be thread-safe. The FilterTraceEvent and -// EndEvent methods can be called concurrently as trace macros are hit on -// different threads. -class BASE_EXPORT TraceEventFilter { - public: - TraceEventFilter(); - virtual ~TraceEventFilter(); - - // If the category is ENABLED_FOR_RECORDING, the event is added iff all the - // filters enabled for the category return true. false causes the event to be - // discarded. - virtual bool FilterTraceEvent(const TraceEvent& trace_event) const = 0; - - // Notifies the end of a duration event when the RAII macro goes out of scope. - virtual void EndEvent(const char* category_name, - const char* event_name) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TraceEventFilter); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_FILTER_H_
diff --git a/base/trace_event/trace_event_filter_test_utils.cc b/base/trace_event/trace_event_filter_test_utils.cc deleted file mode 100644 index 85b4cfa..0000000 --- a/base/trace_event/trace_event_filter_test_utils.cc +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_event_filter_test_utils.h" - -#include "base/logging.h" - -namespace base { -namespace trace_event { - -namespace { -TestEventFilter::HitsCounter* g_hits_counter; -} // namespace; - -// static -const char TestEventFilter::kName[] = "testing_predicate"; -bool TestEventFilter::filter_return_value_; - -// static -std::unique_ptr<TraceEventFilter> TestEventFilter::Factory( - const std::string& predicate_name) { - std::unique_ptr<TraceEventFilter> res; - if (predicate_name == kName) - res.reset(new TestEventFilter()); - return res; -} - -TestEventFilter::TestEventFilter() = default; -TestEventFilter::~TestEventFilter() = default; - -bool TestEventFilter::FilterTraceEvent(const TraceEvent& trace_event) const { - if (g_hits_counter) - g_hits_counter->filter_trace_event_hit_count++; - return filter_return_value_; -} - -void TestEventFilter::EndEvent(const char* category_name, - const char* name) const { - if (g_hits_counter) - g_hits_counter->end_event_hit_count++; -} - -TestEventFilter::HitsCounter::HitsCounter() { - Reset(); - DCHECK(!g_hits_counter); - g_hits_counter = this; -} - -TestEventFilter::HitsCounter::~HitsCounter() { - DCHECK(g_hits_counter); - g_hits_counter = nullptr; -} - -void TestEventFilter::HitsCounter::Reset() { - filter_trace_event_hit_count = 0; - end_event_hit_count = 0; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_event_filter_test_utils.h b/base/trace_event/trace_event_filter_test_utils.h deleted file mode 100644 index 419068b..0000000 --- a/base/trace_event/trace_event_filter_test_utils.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_FILTER_TEST_UTILS_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_FILTER_TEST_UTILS_H_ - -#include <memory> -#include <string> - -#include "base/macros.h" -#include "base/trace_event/trace_event_filter.h" - -namespace base { -namespace trace_event { - -class TestEventFilter : public TraceEventFilter { - public: - struct HitsCounter { - HitsCounter(); - ~HitsCounter(); - void Reset(); - size_t filter_trace_event_hit_count; - size_t end_event_hit_count; - }; - - static const char kName[]; - - // Factory method for TraceLog::SetFilterFactoryForTesting(). - static std::unique_ptr<TraceEventFilter> Factory( - const std::string& predicate_name); - - TestEventFilter(); - ~TestEventFilter() override; - - // TraceEventFilter implementation. - bool FilterTraceEvent(const TraceEvent& trace_event) const override; - void EndEvent(const char* category_name, const char* name) const override; - - static void set_filter_return_value(bool value) { - filter_return_value_ = value; - } - - private: - static bool filter_return_value_; - - DISALLOW_COPY_AND_ASSIGN(TestEventFilter); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_FILTER_TEST_UTILS_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc deleted file mode 100644 index c72e1fc..0000000 --- a/base/trace_event/trace_event_impl.cc +++ /dev/null
@@ -1,489 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_event_impl.h" - -#include <stddef.h> - -#include "base/format_macros.h" -#include "base/json/string_escape.h" -#include "base/memory/ptr_util.h" -#include "base/process/process_handle.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" -#include "base/trace_event/trace_log.h" - -namespace base { -namespace trace_event { - -namespace { - -size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; } - -// Copies |*member| into |*buffer|, sets |*member| to point to this new -// location, and then advances |*buffer| by the amount written. -void CopyTraceEventParameter(char** buffer, - const char** member, - const char* end) { - if (*member) { - size_t written = strlcpy(*buffer, *member, end - *buffer) + 1; - DCHECK_LE(static_cast<int>(written), end - *buffer); - *member = *buffer; - *buffer += written; - } -} - -} // namespace - -TraceEvent::TraceEvent() - : duration_(TimeDelta::FromInternalValue(-1)), - scope_(trace_event_internal::kGlobalScope), - id_(0u), - category_group_enabled_(nullptr), - name_(nullptr), - thread_id_(0), - flags_(0), - phase_(TRACE_EVENT_PHASE_BEGIN) { - for (int i = 0; i < kTraceMaxNumArgs; ++i) - arg_names_[i] = nullptr; - memset(arg_values_, 0, sizeof(arg_values_)); -} - -TraceEvent::~TraceEvent() = default; - -void TraceEvent::MoveFrom(std::unique_ptr<TraceEvent> other) { - timestamp_ = other->timestamp_; - thread_timestamp_ = other->thread_timestamp_; - duration_ = other->duration_; - scope_ = other->scope_; - id_ = other->id_; - category_group_enabled_ = other->category_group_enabled_; - name_ = other->name_; - if (other->flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID) - process_id_ = other->process_id_; - else - thread_id_ = other->thread_id_; - phase_ = other->phase_; - flags_ = other->flags_; - parameter_copy_storage_ = std::move(other->parameter_copy_storage_); - - for (int i = 0; i < kTraceMaxNumArgs; ++i) { - arg_names_[i] = other->arg_names_[i]; - arg_types_[i] = other->arg_types_[i]; - arg_values_[i] = other->arg_values_[i]; - convertable_values_[i] = std::move(other->convertable_values_[i]); - } -} - -void TraceEvent::Initialize( - int thread_id, - TimeTicks timestamp, - ThreadTicks thread_timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - timestamp_ = timestamp; - thread_timestamp_ = thread_timestamp; - duration_ = TimeDelta::FromInternalValue(-1); - scope_ = scope; - id_ = id; - category_group_enabled_ = category_group_enabled; - name_ = name; - thread_id_ = thread_id; - phase_ = phase; - flags_ = flags; - bind_id_ = bind_id; - - // Clamp num_args since it may have been set by a third_party library. - num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; - int i = 0; - for (; i < num_args; ++i) { - arg_names_[i] = arg_names[i]; - arg_types_[i] = arg_types[i]; - - if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) { - convertable_values_[i] = std::move(convertable_values[i]); - } else { - arg_values_[i].as_uint = arg_values[i]; - convertable_values_[i].reset(); - } - } - for (; i < kTraceMaxNumArgs; ++i) { - arg_names_[i] = nullptr; - arg_values_[i].as_uint = 0u; - convertable_values_[i].reset(); - arg_types_[i] = TRACE_VALUE_TYPE_UINT; - } - - bool copy = !!(flags & TRACE_EVENT_FLAG_COPY); - size_t alloc_size = 0; - if (copy) { - alloc_size += GetAllocLength(name) + GetAllocLength(scope); - for (i = 0; i < num_args; ++i) { - alloc_size += GetAllocLength(arg_names_[i]); - if (arg_types_[i] == TRACE_VALUE_TYPE_STRING) - arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING; - } - } - - bool arg_is_copy[kTraceMaxNumArgs]; - for (i = 0; i < num_args; ++i) { - // No copying of convertable types, we retain ownership. - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - continue; - - // We only take a copy of arg_vals if they are of type COPY_STRING. - arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING); - if (arg_is_copy[i]) - alloc_size += GetAllocLength(arg_values_[i].as_string); - } - - if (alloc_size) { - parameter_copy_storage_.reset(new std::string); - parameter_copy_storage_->resize(alloc_size); - char* ptr = base::data(*parameter_copy_storage_); - const char* end = ptr + alloc_size; - if (copy) { - CopyTraceEventParameter(&ptr, &name_, end); - CopyTraceEventParameter(&ptr, &scope_, end); - for (i = 0; i < num_args; ++i) { - CopyTraceEventParameter(&ptr, &arg_names_[i], end); - } - } - for (i = 0; i < num_args; ++i) { - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - continue; - if (arg_is_copy[i]) - CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end); - } - DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; - } -} - -void TraceEvent::Reset() { - // Only reset fields that won't be initialized in Initialize(), or that may - // hold references to other objects. - duration_ = TimeDelta::FromInternalValue(-1); - parameter_copy_storage_.reset(); - for (int i = 0; i < kTraceMaxNumArgs; ++i) - convertable_values_[i].reset(); -} - -void TraceEvent::UpdateDuration(const TimeTicks& now, - const ThreadTicks& thread_now) { - DCHECK_EQ(duration_.ToInternalValue(), -1); - duration_ = now - timestamp_; - - // |thread_timestamp_| can be empty if the thread ticks clock wasn't - // initialized when it was recorded. - if (thread_timestamp_ != ThreadTicks()) - thread_duration_ = thread_now - thread_timestamp_; -} - -void TraceEvent::EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) { - overhead->Add(TraceEventMemoryOverhead::kTraceEvent, sizeof(*this)); - - if (parameter_copy_storage_) - overhead->AddString(*parameter_copy_storage_); - - for (size_t i = 0; i < kTraceMaxNumArgs; ++i) { - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values_[i]->EstimateTraceMemoryOverhead(overhead); - } -} - -// static -void TraceEvent::AppendValueAsJSON(unsigned char type, - TraceEvent::TraceValue value, - std::string* out) { - switch (type) { - case TRACE_VALUE_TYPE_BOOL: - *out += value.as_bool ? "true" : "false"; - break; - case TRACE_VALUE_TYPE_UINT: - StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(value.as_uint)); - break; - case TRACE_VALUE_TYPE_INT: - StringAppendF(out, "%" PRId64, static_cast<int64_t>(value.as_int)); - break; - case TRACE_VALUE_TYPE_DOUBLE: { - // FIXME: base/json/json_writer.cc is using the same code, - // should be made into a common method. - std::string real; - double val = value.as_double; - if (std::isfinite(val)) { - real = NumberToString(val); - // Ensure that the number has a .0 if there's no decimal or 'e'. This - // makes sure that when we read the JSON back, it's interpreted as a - // real rather than an int. - if (real.find('.') == std::string::npos && - real.find('e') == std::string::npos && - real.find('E') == std::string::npos) { - real.append(".0"); - } - // The JSON spec requires that non-integer values in the range (-1,1) - // have a zero before the decimal point - ".52" is not valid, "0.52" is. - if (real[0] == '.') { - real.insert(0, "0"); - } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { - // "-.1" bad "-0.1" good - real.insert(1, "0"); - } - } else if (std::isnan(val)){ - // The JSON spec doesn't allow NaN and Infinity (since these are - // objects in EcmaScript). Use strings instead. - real = "\"NaN\""; - } else if (val < 0) { - real = "\"-Infinity\""; - } else { - real = "\"Infinity\""; - } - StringAppendF(out, "%s", real.c_str()); - break; - } - case TRACE_VALUE_TYPE_POINTER: - // JSON only supports double and int numbers. - // So as not to lose bits from a 64-bit pointer, output as a hex string. - StringAppendF( - out, "\"0x%" PRIx64 "\"", - static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value.as_pointer))); - break; - case TRACE_VALUE_TYPE_STRING: - case TRACE_VALUE_TYPE_COPY_STRING: - EscapeJSONString(value.as_string ? value.as_string : "NULL", true, out); - break; - default: - NOTREACHED() << "Don't know how to print this value"; - break; - } -} - -void TraceEvent::AppendAsJSON( - std::string* out, - const ArgumentFilterPredicate& argument_filter_predicate) const { - int64_t time_int64 = timestamp_.ToInternalValue(); - int process_id; - int thread_id; - if ((flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID) && - process_id_ != kNullProcessId) { - process_id = process_id_; - thread_id = -1; - } else { - process_id = TraceLog::GetInstance()->process_id(); - thread_id = thread_id_; - } - const char* category_group_name = - TraceLog::GetCategoryGroupName(category_group_enabled_); - - // Category group checked at category creation time. - DCHECK(!strchr(name_, '"')); - StringAppendF(out, "{\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 - ",\"ph\":\"%c\",\"cat\":\"%s\",\"name\":", - process_id, thread_id, time_int64, phase_, category_group_name); - EscapeJSONString(name_, true, out); - *out += ",\"args\":"; - - // Output argument names and values, stop at first NULL argument name. - // TODO(oysteine): The dual predicates here is a bit ugly; if the filtering - // capabilities need to grow even more precise we should rethink this - // approach - ArgumentNameFilterPredicate argument_name_filter_predicate; - bool strip_args = - arg_names_[0] && !argument_filter_predicate.is_null() && - !argument_filter_predicate.Run(category_group_name, name_, - &argument_name_filter_predicate); - - if (strip_args) { - *out += "\"__stripped__\""; - } else { - *out += "{"; - - for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { - if (i > 0) - *out += ","; - *out += "\""; - *out += arg_names_[i]; - *out += "\":"; - - if (argument_name_filter_predicate.is_null() || - argument_name_filter_predicate.Run(arg_names_[i])) { - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values_[i]->AppendAsTraceFormat(out); - else - AppendValueAsJSON(arg_types_[i], arg_values_[i], out); - } else { - *out += "\"__stripped__\""; - } - } - - *out += "}"; - } - - if (phase_ == TRACE_EVENT_PHASE_COMPLETE) { - int64_t duration = duration_.ToInternalValue(); - if (duration != -1) - StringAppendF(out, ",\"dur\":%" PRId64, duration); - if (!thread_timestamp_.is_null()) { - int64_t thread_duration = thread_duration_.ToInternalValue(); - if (thread_duration != -1) - StringAppendF(out, ",\"tdur\":%" PRId64, thread_duration); - } - } - - // Output tts if thread_timestamp is valid. - if (!thread_timestamp_.is_null()) { - int64_t thread_time_int64 = thread_timestamp_.ToInternalValue(); - StringAppendF(out, ",\"tts\":%" PRId64, thread_time_int64); - } - - // Output async tts marker field if flag is set. - if (flags_ & TRACE_EVENT_FLAG_ASYNC_TTS) { - StringAppendF(out, ", \"use_async_tts\":1"); - } - - // If id_ is set, print it out as a hex string so we don't loose any - // bits (it might be a 64-bit pointer). - unsigned int id_flags_ = flags_ & (TRACE_EVENT_FLAG_HAS_ID | - TRACE_EVENT_FLAG_HAS_LOCAL_ID | - TRACE_EVENT_FLAG_HAS_GLOBAL_ID); - if (id_flags_) { - if (scope_ != trace_event_internal::kGlobalScope) - StringAppendF(out, ",\"scope\":\"%s\"", scope_); - - switch (id_flags_) { - case TRACE_EVENT_FLAG_HAS_ID: - StringAppendF(out, ",\"id\":\"0x%" PRIx64 "\"", - static_cast<uint64_t>(id_)); - break; - - case TRACE_EVENT_FLAG_HAS_LOCAL_ID: - StringAppendF(out, ",\"id2\":{\"local\":\"0x%" PRIx64 "\"}", - static_cast<uint64_t>(id_)); - break; - - case TRACE_EVENT_FLAG_HAS_GLOBAL_ID: - StringAppendF(out, ",\"id2\":{\"global\":\"0x%" PRIx64 "\"}", - static_cast<uint64_t>(id_)); - break; - - default: - NOTREACHED() << "More than one of the ID flags are set"; - break; - } - } - - if (flags_ & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING) - StringAppendF(out, ",\"bp\":\"e\""); - - if ((flags_ & TRACE_EVENT_FLAG_FLOW_OUT) || - (flags_ & TRACE_EVENT_FLAG_FLOW_IN)) { - StringAppendF(out, ",\"bind_id\":\"0x%" PRIx64 "\"", - static_cast<uint64_t>(bind_id_)); - } - if (flags_ & TRACE_EVENT_FLAG_FLOW_IN) - StringAppendF(out, ",\"flow_in\":true"); - if (flags_ & TRACE_EVENT_FLAG_FLOW_OUT) - StringAppendF(out, ",\"flow_out\":true"); - - // Instant events also output their scope. - if (phase_ == TRACE_EVENT_PHASE_INSTANT) { - char scope = '?'; - switch (flags_ & TRACE_EVENT_FLAG_SCOPE_MASK) { - case TRACE_EVENT_SCOPE_GLOBAL: - scope = TRACE_EVENT_SCOPE_NAME_GLOBAL; - break; - - case TRACE_EVENT_SCOPE_PROCESS: - scope = TRACE_EVENT_SCOPE_NAME_PROCESS; - break; - - case TRACE_EVENT_SCOPE_THREAD: - scope = TRACE_EVENT_SCOPE_NAME_THREAD; - break; - } - StringAppendF(out, ",\"s\":\"%c\"", scope); - } - - *out += "}"; -} - -void TraceEvent::AppendPrettyPrinted(std::ostringstream* out) const { - *out << name_ << "["; - *out << TraceLog::GetCategoryGroupName(category_group_enabled_); - *out << "]"; - if (arg_names_[0]) { - *out << ", {"; - for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { - if (i > 0) - *out << ", "; - *out << arg_names_[i] << ":"; - std::string value_as_text; - - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values_[i]->AppendAsTraceFormat(&value_as_text); - else - AppendValueAsJSON(arg_types_[i], arg_values_[i], &value_as_text); - - *out << value_as_text; - } - *out << "}"; - } -} - -} // namespace trace_event -} // namespace base - -namespace trace_event_internal { - -std::unique_ptr<base::trace_event::ConvertableToTraceFormat> -TraceID::AsConvertableToTraceFormat() const { - auto value = std::make_unique<base::trace_event::TracedValue>(); - - if (scope_ != kGlobalScope) - value->SetString("scope", scope_); - - const char* id_field_name = "id"; - if (id_flags_ == TRACE_EVENT_FLAG_HAS_GLOBAL_ID) { - id_field_name = "global"; - value->BeginDictionary("id2"); - } else if (id_flags_ == TRACE_EVENT_FLAG_HAS_LOCAL_ID) { - id_field_name = "local"; - value->BeginDictionary("id2"); - } else if (id_flags_ != TRACE_EVENT_FLAG_HAS_ID) { - NOTREACHED() << "Unrecognized ID flag"; - } - - if (has_prefix_) { - value->SetString(id_field_name, - base::StringPrintf("0x%" PRIx64 "/0x%" PRIx64, - static_cast<uint64_t>(prefix_), - static_cast<uint64_t>(raw_id_))); - } else { - value->SetString( - id_field_name, - base::StringPrintf("0x%" PRIx64, static_cast<uint64_t>(raw_id_))); - } - - if (id_flags_ != TRACE_EVENT_FLAG_HAS_ID) - value->EndDictionary(); - - return std::move(value); -} - -} // namespace trace_event_internal
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h deleted file mode 100644 index af47f49..0000000 --- a/base/trace_event/trace_event_impl.h +++ /dev/null
@@ -1,187 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/callback.h" -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "base/observer_list.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_util.h" -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_local.h" -#include "base/trace_event/trace_event_memory_overhead.h" -#include "build_config.h" - -namespace base { -namespace trace_event { - -typedef base::Callback<bool(const char* arg_name)> ArgumentNameFilterPredicate; - -typedef base::Callback<bool(const char* category_group_name, - const char* event_name, - ArgumentNameFilterPredicate*)> - ArgumentFilterPredicate; - -// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided -// class must implement this interface. -class BASE_EXPORT ConvertableToTraceFormat { - public: - ConvertableToTraceFormat() = default; - virtual ~ConvertableToTraceFormat() = default; - - // Append the class info to the provided |out| string. The appended - // data must be a valid JSON object. Strings must be properly quoted, and - // escaped. There is no processing applied to the content after it is - // appended. - virtual void AppendAsTraceFormat(std::string* out) const = 0; - - virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); - - std::string ToString() const { - std::string result; - AppendAsTraceFormat(&result); - return result; - } - - private: - DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat); -}; - -const int kTraceMaxNumArgs = 2; - -struct TraceEventHandle { - uint32_t chunk_seq; - // These numbers of bits must be kept consistent with - // TraceBufferChunk::kMaxTrunkIndex and - // TraceBufferChunk::kTraceBufferChunkSize (in trace_buffer.h). - unsigned chunk_index : 26; - unsigned event_index : 6; -}; - -class BASE_EXPORT TraceEvent { - public: - union TraceValue { - bool as_bool; - unsigned long long as_uint; - long long as_int; - double as_double; - const void* as_pointer; - const char* as_string; - }; - - TraceEvent(); - ~TraceEvent(); - - void MoveFrom(std::unique_ptr<TraceEvent> other); - - void Initialize(int thread_id, - TimeTicks timestamp, - ThreadTicks thread_timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); - - void Reset(); - - void UpdateDuration(const TimeTicks& now, const ThreadTicks& thread_now); - - void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); - - // Serialize event data to JSON - void AppendAsJSON( - std::string* out, - const ArgumentFilterPredicate& argument_filter_predicate) const; - void AppendPrettyPrinted(std::ostringstream* out) const; - - static void AppendValueAsJSON(unsigned char type, - TraceValue value, - std::string* out); - - TimeTicks timestamp() const { return timestamp_; } - ThreadTicks thread_timestamp() const { return thread_timestamp_; } - char phase() const { return phase_; } - int thread_id() const { return thread_id_; } - TimeDelta duration() const { return duration_; } - TimeDelta thread_duration() const { return thread_duration_; } - const char* scope() const { return scope_; } - unsigned long long id() const { return id_; } - unsigned int flags() const { return flags_; } - unsigned long long bind_id() const { return bind_id_; } - // Exposed for unittesting: - - const std::string* parameter_copy_storage() const { - return parameter_copy_storage_.get(); - } - - const unsigned char* category_group_enabled() const { - return category_group_enabled_; - } - - const char* name() const { return name_; } - - unsigned char arg_type(size_t index) const { return arg_types_[index]; } - const char* arg_name(size_t index) const { return arg_names_[index]; } - const TraceValue& arg_value(size_t index) const { return arg_values_[index]; } - -#if defined(OS_ANDROID) - void SendToATrace(); -#endif - - private: - // Note: these are ordered by size (largest first) for optimal packing. - TimeTicks timestamp_; - ThreadTicks thread_timestamp_; - TimeDelta duration_; - TimeDelta thread_duration_; - // scope_ and id_ can be used to store phase-specific data. - const char* scope_; - unsigned long long id_; - TraceValue arg_values_[kTraceMaxNumArgs]; - const char* arg_names_[kTraceMaxNumArgs]; - std::unique_ptr<ConvertableToTraceFormat> - convertable_values_[kTraceMaxNumArgs]; - const unsigned char* category_group_enabled_; - const char* name_; - std::unique_ptr<std::string> parameter_copy_storage_; - // Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either: - // tid: thread_id_, pid: current_process_id (default case). - // tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID). - union { - int thread_id_; - int process_id_; - }; - unsigned int flags_; - unsigned long long bind_id_; - unsigned char arg_types_[kTraceMaxNumArgs]; - char phase_; - - DISALLOW_COPY_AND_ASSIGN(TraceEvent); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
diff --git a/base/trace_event/trace_event_memory_overhead.cc b/base/trace_event/trace_event_memory_overhead.cc deleted file mode 100644 index d5875f8..0000000 --- a/base/trace_event/trace_event_memory_overhead.cc +++ /dev/null
@@ -1,177 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_event_memory_overhead.h" - -#include <algorithm> - -#include "base/bits.h" -#include "base/memory/ref_counted_memory.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/memory_usage_estimator.h" -#include "base/trace_event/process_memory_dump.h" -#include "base/values.h" - -namespace base { -namespace trace_event { - -namespace { - -const char* ObjectTypeToString(TraceEventMemoryOverhead::ObjectType type) { - switch (type) { - case TraceEventMemoryOverhead::kOther: - return "(Other)"; - case TraceEventMemoryOverhead::kTraceBuffer: - return "TraceBuffer"; - case TraceEventMemoryOverhead::kTraceBufferChunk: - return "TraceBufferChunk"; - case TraceEventMemoryOverhead::kTraceEvent: - return "TraceEvent"; - case TraceEventMemoryOverhead::kUnusedTraceEvent: - return "TraceEvent(Unused)"; - case TraceEventMemoryOverhead::kTracedValue: - return "TracedValue"; - case TraceEventMemoryOverhead::kConvertableToTraceFormat: - return "ConvertableToTraceFormat"; - case TraceEventMemoryOverhead::kHeapProfilerAllocationRegister: - return "AllocationRegister"; - case TraceEventMemoryOverhead::kHeapProfilerTypeNameDeduplicator: - return "TypeNameDeduplicator"; - case TraceEventMemoryOverhead::kHeapProfilerStackFrameDeduplicator: - return "StackFrameDeduplicator"; - case TraceEventMemoryOverhead::kStdString: - return "std::string"; - case TraceEventMemoryOverhead::kBaseValue: - return "base::Value"; - case TraceEventMemoryOverhead::kTraceEventMemoryOverhead: - return "TraceEventMemoryOverhead"; - case TraceEventMemoryOverhead::kLast: - NOTREACHED(); - } - NOTREACHED(); - return "BUG"; -} - -} // namespace - -TraceEventMemoryOverhead::TraceEventMemoryOverhead() : allocated_objects_() {} - -TraceEventMemoryOverhead::~TraceEventMemoryOverhead() = default; - -void TraceEventMemoryOverhead::AddInternal(ObjectType object_type, - size_t count, - size_t allocated_size_in_bytes, - size_t resident_size_in_bytes) { - ObjectCountAndSize& count_and_size = - allocated_objects_[static_cast<uint32_t>(object_type)]; - count_and_size.count += count; - count_and_size.allocated_size_in_bytes += allocated_size_in_bytes; - count_and_size.resident_size_in_bytes += resident_size_in_bytes; -} - -void TraceEventMemoryOverhead::Add(ObjectType object_type, - size_t allocated_size_in_bytes) { - Add(object_type, allocated_size_in_bytes, allocated_size_in_bytes); -} - -void TraceEventMemoryOverhead::Add(ObjectType object_type, - size_t allocated_size_in_bytes, - size_t resident_size_in_bytes) { - AddInternal(object_type, 1, allocated_size_in_bytes, resident_size_in_bytes); -} - -void TraceEventMemoryOverhead::AddString(const std::string& str) { - Add(kStdString, EstimateMemoryUsage(str)); -} - -void TraceEventMemoryOverhead::AddRefCountedString( - const RefCountedString& str) { - Add(kOther, sizeof(RefCountedString)); - AddString(str.data()); -} - -void TraceEventMemoryOverhead::AddValue(const Value& value) { - switch (value.type()) { - case Value::Type::NONE: - case Value::Type::BOOLEAN: - case Value::Type::INTEGER: - case Value::Type::DOUBLE: - Add(kBaseValue, sizeof(Value)); - break; - - case Value::Type::STRING: { - const Value* string_value = nullptr; - value.GetAsString(&string_value); - Add(kBaseValue, sizeof(Value)); - AddString(string_value->GetString()); - } break; - - case Value::Type::BINARY: { - Add(kBaseValue, sizeof(Value) + value.GetBlob().size()); - } break; - - case Value::Type::DICTIONARY: { - const DictionaryValue* dictionary_value = nullptr; - value.GetAsDictionary(&dictionary_value); - Add(kBaseValue, sizeof(DictionaryValue)); - for (DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd(); - it.Advance()) { - AddString(it.key()); - AddValue(it.value()); - } - } break; - - case Value::Type::LIST: { - const ListValue* list_value = nullptr; - value.GetAsList(&list_value); - Add(kBaseValue, sizeof(ListValue)); - for (const auto& v : *list_value) - AddValue(v); - } break; - - default: - NOTREACHED(); - } -} - -void TraceEventMemoryOverhead::AddSelf() { - Add(kTraceEventMemoryOverhead, sizeof(*this)); -} - -size_t TraceEventMemoryOverhead::GetCount(ObjectType object_type) const { - CHECK(object_type < kLast); - return allocated_objects_[static_cast<uint32_t>(object_type)].count; -} - -void TraceEventMemoryOverhead::Update(const TraceEventMemoryOverhead& other) { - for (uint32_t i = 0; i < kLast; i++) { - const ObjectCountAndSize& other_entry = other.allocated_objects_[i]; - AddInternal(static_cast<ObjectType>(i), other_entry.count, - other_entry.allocated_size_in_bytes, - other_entry.resident_size_in_bytes); - } -} - -void TraceEventMemoryOverhead::DumpInto(const char* base_name, - ProcessMemoryDump* pmd) const { - for (uint32_t i = 0; i < kLast; i++) { - const ObjectCountAndSize& count_and_size = allocated_objects_[i]; - if (count_and_size.allocated_size_in_bytes == 0) - continue; - std::string dump_name = StringPrintf( - "%s/%s", base_name, ObjectTypeToString(static_cast<ObjectType>(i))); - MemoryAllocatorDump* mad = pmd->CreateAllocatorDump(dump_name); - mad->AddScalar(MemoryAllocatorDump::kNameSize, - MemoryAllocatorDump::kUnitsBytes, - count_and_size.allocated_size_in_bytes); - mad->AddScalar("resident_size", MemoryAllocatorDump::kUnitsBytes, - count_and_size.resident_size_in_bytes); - mad->AddScalar(MemoryAllocatorDump::kNameObjectCount, - MemoryAllocatorDump::kUnitsObjects, count_and_size.count); - } -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_event_memory_overhead.h b/base/trace_event/trace_event_memory_overhead.h deleted file mode 100644 index 1587a30..0000000 --- a/base/trace_event/trace_event_memory_overhead.h +++ /dev/null
@@ -1,94 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <unordered_map> - -#include "base/base_export.h" -#include "base/macros.h" - -namespace base { - -class RefCountedString; -class Value; - -namespace trace_event { - -class ProcessMemoryDump; - -// Used to estimate the memory overhead of the tracing infrastructure. -class BASE_EXPORT TraceEventMemoryOverhead { - public: - enum ObjectType : uint32_t { - kOther = 0, - kTraceBuffer, - kTraceBufferChunk, - kTraceEvent, - kUnusedTraceEvent, - kTracedValue, - kConvertableToTraceFormat, - kHeapProfilerAllocationRegister, - kHeapProfilerTypeNameDeduplicator, - kHeapProfilerStackFrameDeduplicator, - kStdString, - kBaseValue, - kTraceEventMemoryOverhead, - kLast - }; - - TraceEventMemoryOverhead(); - ~TraceEventMemoryOverhead(); - - // Use this method to account the overhead of an object for which an estimate - // is known for both the allocated and resident memory. - void Add(ObjectType object_type, - size_t allocated_size_in_bytes, - size_t resident_size_in_bytes); - - // Similar to Add() above, but assumes that - // |resident_size_in_bytes| == |allocated_size_in_bytes|. - void Add(ObjectType object_type, size_t allocated_size_in_bytes); - - // Specialized profiling functions for commonly used object types. - void AddString(const std::string& str); - void AddValue(const Value& value); - void AddRefCountedString(const RefCountedString& str); - - // Call this after all the Add* methods above to account the memory used by - // this TraceEventMemoryOverhead instance itself. - void AddSelf(); - - // Retrieves the count, that is, the count of Add*(|object_type|, ...) calls. - size_t GetCount(ObjectType object_type) const; - - // Adds up and merges all the values from |other| to this instance. - void Update(const TraceEventMemoryOverhead& other); - - void DumpInto(const char* base_name, ProcessMemoryDump* pmd) const; - - private: - struct ObjectCountAndSize { - size_t count; - size_t allocated_size_in_bytes; - size_t resident_size_in_bytes; - }; - ObjectCountAndSize allocated_objects_[ObjectType::kLast]; - - void AddInternal(ObjectType object_type, - size_t count, - size_t allocated_size_in_bytes, - size_t resident_size_in_bytes); - - DISALLOW_COPY_AND_ASSIGN(TraceEventMemoryOverhead); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_
diff --git a/base/trace_event/trace_event_system_stats_monitor.cc b/base/trace_event/trace_event_system_stats_monitor.cc deleted file mode 100644 index 7e082f3..0000000 --- a/base/trace_event/trace_event_system_stats_monitor.cc +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_event_system_stats_monitor.h" - -#include <memory> - -#include "base/debug/leak_annotations.h" -#include "base/json/json_writer.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/process/process_metrics.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/threading/thread_local_storage.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace trace_event { - -namespace { - -///////////////////////////////////////////////////////////////////////////// -// Holds profiled system stats until the tracing system needs to serialize it. -class SystemStatsHolder : public base::trace_event::ConvertableToTraceFormat { - public: - SystemStatsHolder() = default; - ~SystemStatsHolder() override = default; - - // Fills system_metrics_ with profiled system memory and disk stats. - // Uses the previous stats to compute rates if this is not the first profile. - void GetSystemProfilingStats(); - - // base::trace_event::ConvertableToTraceFormat overrides: - void AppendAsTraceFormat(std::string* out) const override { - AppendSystemProfileAsTraceFormat(system_stats_, out); - } - - private: - SystemMetrics system_stats_; - - DISALLOW_COPY_AND_ASSIGN(SystemStatsHolder); -}; - -void SystemStatsHolder::GetSystemProfilingStats() { - system_stats_ = SystemMetrics::Sample(); -} - -} // namespace - -////////////////////////////////////////////////////////////////////////////// - -TraceEventSystemStatsMonitor::TraceEventSystemStatsMonitor( - scoped_refptr<SingleThreadTaskRunner> task_runner) - : task_runner_(task_runner), - weak_factory_(this) { - // Force the "system_stats" category to show up in the trace viewer. - TraceLog::GetCategoryGroupEnabled(TRACE_DISABLED_BY_DEFAULT("system_stats")); - - // Allow this to be instantiated on unsupported platforms, but don't run. - TraceLog::GetInstance()->AddEnabledStateObserver(this); -} - -TraceEventSystemStatsMonitor::~TraceEventSystemStatsMonitor() { - if (dump_timer_.IsRunning()) - StopProfiling(); - TraceLog::GetInstance()->RemoveEnabledStateObserver(this); -} - -void TraceEventSystemStatsMonitor::OnTraceLogEnabled() { - // Check to see if system tracing is enabled. - bool enabled; - - TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT( - "system_stats"), &enabled); - if (!enabled) - return; - task_runner_->PostTask( - FROM_HERE, base::BindOnce(&TraceEventSystemStatsMonitor::StartProfiling, - weak_factory_.GetWeakPtr())); -} - -void TraceEventSystemStatsMonitor::OnTraceLogDisabled() { - task_runner_->PostTask( - FROM_HERE, base::BindOnce(&TraceEventSystemStatsMonitor::StopProfiling, - weak_factory_.GetWeakPtr())); -} - -void TraceEventSystemStatsMonitor::StartProfiling() { - // Watch for the tracing framework sending enabling more than once. - if (dump_timer_.IsRunning()) - return; - - dump_timer_.Start(FROM_HERE, - TimeDelta::FromMilliseconds(TraceEventSystemStatsMonitor:: - kSamplingIntervalMilliseconds), - base::Bind(&TraceEventSystemStatsMonitor:: - DumpSystemStats, - weak_factory_.GetWeakPtr())); -} - -// If system tracing is enabled, dumps a profile to the tracing system. -void TraceEventSystemStatsMonitor::DumpSystemStats() { - std::unique_ptr<SystemStatsHolder> dump_holder(new SystemStatsHolder()); - dump_holder->GetSystemProfilingStats(); - - TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( - TRACE_DISABLED_BY_DEFAULT("system_stats"), - "base::TraceEventSystemStatsMonitor::SystemStats", this, - std::move(dump_holder)); -} - -void TraceEventSystemStatsMonitor::StopProfiling() { - dump_timer_.Stop(); -} - -bool TraceEventSystemStatsMonitor::IsTimerRunningForTest() const { - return dump_timer_.IsRunning(); -} - -void AppendSystemProfileAsTraceFormat(const SystemMetrics& system_metrics, - std::string* output) { - std::string tmp; - base::JSONWriter::Write(*system_metrics.ToValue(), &tmp); - *output += tmp; -} - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/trace_event_system_stats_monitor.h b/base/trace_event/trace_event_system_stats_monitor.h deleted file mode 100644 index 14aa568..0000000 --- a/base/trace_event/trace_event_system_stats_monitor.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ - -#include "base/base_export.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/process/process_metrics.h" -#include "base/timer/timer.h" -#include "base/trace_event/trace_log.h" - -namespace base { - -class SingleThreadTaskRunner; - -namespace trace_event { - -// Watches for chrome://tracing to be enabled or disabled. When tracing is -// enabled, also enables system events profiling. This class is the preferred -// way to turn system tracing on and off. -class BASE_EXPORT TraceEventSystemStatsMonitor - : public TraceLog::EnabledStateObserver { - public: - // Length of time interval between stat profiles. - static const int kSamplingIntervalMilliseconds = 2000; - - // |task_runner| must be the primary thread for the client - // process, e.g. the UI thread in a browser. - explicit TraceEventSystemStatsMonitor( - scoped_refptr<SingleThreadTaskRunner> task_runner); - - ~TraceEventSystemStatsMonitor() override; - - // base::trace_event::TraceLog::EnabledStateChangedObserver overrides: - void OnTraceLogEnabled() override; - void OnTraceLogDisabled() override; - - // Retrieves system profiling at the current time. - void DumpSystemStats(); - - private: - FRIEND_TEST_ALL_PREFIXES(TraceSystemStatsMonitorTest, - TraceEventSystemStatsMonitor); - - bool IsTimerRunningForTest() const; - - void StartProfiling(); - - void StopProfiling(); - - // Ensures the observer starts and stops tracing on the primary thread. - scoped_refptr<SingleThreadTaskRunner> task_runner_; - - // Timer to schedule system profile dumps. - RepeatingTimer dump_timer_; - - WeakPtrFactory<TraceEventSystemStatsMonitor> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(TraceEventSystemStatsMonitor); -}; - -// Converts system memory profiling stats in |input| to -// trace event compatible JSON and appends to |output|. Visible for testing. -BASE_EXPORT void AppendSystemProfileAsTraceFormat(const SystemMetrics& - system_stats, - std::string* output); - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc deleted file mode 100644 index f608261..0000000 --- a/base/trace_event/trace_log.cc +++ /dev/null
@@ -1,1743 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_log.h" - -#include <algorithm> -#include <cmath> -#include <memory> -#include <utility> - -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/debug/leak_annotations.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted_memory.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_current.h" -#include "base/no_destructor.h" -#include "base/process/process_info.h" -#include "base/process/process_metrics.h" -#include "base/stl_util.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_split.h" -#include "base/strings/string_tokenizer.h" -#include "base/strings/stringprintf.h" -#include "base/sys_info.h" -#include "base/task_scheduler/post_task.h" -#include "base/threading/platform_thread.h" -#include "base/threading/thread_id_name_manager.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "base/trace_event/category_registry.h" -#include "base/trace_event/event_name_filter.h" -#include "base/trace_event/heap_profiler.h" -#include "base/trace_event/heap_profiler_allocation_context_tracker.h" -#include "base/trace_event/heap_profiler_event_filter.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/memory_dump_provider.h" -#include "base/trace_event/process_memory_dump.h" -#include "base/trace_event/trace_buffer.h" -#include "base/trace_event/trace_event.h" -#include "build_config.h" - -#if defined(OS_ANDROID) -// The linker assigns the virtual address of the start of current library to -// this symbol. -extern char __executable_start; -#endif - -namespace base { -namespace trace_event { - -namespace { - -// Controls the number of trace events we will buffer in-memory -// before throwing them away. -const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize; - -const size_t kTraceEventVectorBigBufferChunks = - 512000000 / kTraceBufferChunkSize; -static_assert( - kTraceEventVectorBigBufferChunks <= TraceBufferChunk::kMaxChunkIndex, - "Too many big buffer chunks"); -const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize; -static_assert( - kTraceEventVectorBufferChunks <= TraceBufferChunk::kMaxChunkIndex, - "Too many vector buffer chunks"); -const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; - -// ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. -const size_t kEchoToConsoleTraceEventBufferChunks = 256; - -const size_t kTraceEventBufferSizeInBytes = 100 * 1024; -const int kThreadFlushTimeoutMs = 3000; - -TraceLog* g_trace_log_for_testing = nullptr; - -#define MAX_TRACE_EVENT_FILTERS 32 - -// List of TraceEventFilter objects from the most recent tracing session. -std::vector<std::unique_ptr<TraceEventFilter>>& GetCategoryGroupFilters() { - static auto* filters = new std::vector<std::unique_ptr<TraceEventFilter>>(); - return *filters; -} - -ThreadTicks ThreadNow() { - return ThreadTicks::IsSupported() - ? base::subtle::ThreadTicksNowIgnoringOverride() - : ThreadTicks(); -} - -template <typename T> -void InitializeMetadataEvent(TraceEvent* trace_event, - int thread_id, - const char* metadata_name, - const char* arg_name, - const T& value) { - if (!trace_event) - return; - - int num_args = 1; - unsigned char arg_type; - unsigned long long arg_value; - ::trace_event_internal::SetTraceValue(value, &arg_type, &arg_value); - trace_event->Initialize( - thread_id, - TimeTicks(), - ThreadTicks(), - TRACE_EVENT_PHASE_METADATA, - CategoryRegistry::kCategoryMetadata->state_ptr(), - metadata_name, - trace_event_internal::kGlobalScope, // scope - trace_event_internal::kNoId, // id - trace_event_internal::kNoId, // bind_id - num_args, - &arg_name, - &arg_type, - &arg_value, - nullptr, - TRACE_EVENT_FLAG_NONE); -} - -class AutoThreadLocalBoolean { - public: - explicit AutoThreadLocalBoolean(ThreadLocalBoolean* thread_local_boolean) - : thread_local_boolean_(thread_local_boolean) { - DCHECK(!thread_local_boolean_->Get()); - thread_local_boolean_->Set(true); - } - ~AutoThreadLocalBoolean() { thread_local_boolean_->Set(false); } - - private: - ThreadLocalBoolean* thread_local_boolean_; - DISALLOW_COPY_AND_ASSIGN(AutoThreadLocalBoolean); -}; - -// Use this function instead of TraceEventHandle constructor to keep the -// overhead of ScopedTracer (trace_event.h) constructor minimum. -void MakeHandle(uint32_t chunk_seq, - size_t chunk_index, - size_t event_index, - TraceEventHandle* handle) { - DCHECK(chunk_seq); - DCHECK(chunk_index <= TraceBufferChunk::kMaxChunkIndex); - DCHECK(event_index < TraceBufferChunk::kTraceBufferChunkSize); - DCHECK(chunk_index <= std::numeric_limits<uint16_t>::max()); - handle->chunk_seq = chunk_seq; - handle->chunk_index = static_cast<uint16_t>(chunk_index); - handle->event_index = static_cast<uint16_t>(event_index); -} - -template <typename Function> -void ForEachCategoryFilter(const unsigned char* category_group_enabled, - Function filter_fn) { - const TraceCategory* category = - CategoryRegistry::GetCategoryByStatePtr(category_group_enabled); - uint32_t filter_bitmap = category->enabled_filters(); - for (int index = 0; filter_bitmap != 0; filter_bitmap >>= 1, index++) { - if (filter_bitmap & 1 && GetCategoryGroupFilters()[index]) - filter_fn(GetCategoryGroupFilters()[index].get()); - } -} - -} // namespace - -// A helper class that allows the lock to be acquired in the middle of the scope -// and unlocks at the end of scope if locked. -class TraceLog::OptionalAutoLock { - public: - explicit OptionalAutoLock(Lock* lock) : lock_(lock), locked_(false) {} - - ~OptionalAutoLock() { - if (locked_) - lock_->Release(); - } - - void EnsureAcquired() { - if (!locked_) { - lock_->Acquire(); - locked_ = true; - } - } - - private: - Lock* lock_; - bool locked_; - DISALLOW_COPY_AND_ASSIGN(OptionalAutoLock); -}; - -class TraceLog::ThreadLocalEventBuffer - : public MessageLoopCurrent::DestructionObserver, - public MemoryDumpProvider { - public: - explicit ThreadLocalEventBuffer(TraceLog* trace_log); - ~ThreadLocalEventBuffer() override; - - TraceEvent* AddTraceEvent(TraceEventHandle* handle); - - TraceEvent* GetEventByHandle(TraceEventHandle handle) { - if (!chunk_ || handle.chunk_seq != chunk_->seq() || - handle.chunk_index != chunk_index_) { - return nullptr; - } - - return chunk_->GetEventAt(handle.event_index); - } - - int generation() const { return generation_; } - - private: - // MessageLoopCurrent::DestructionObserver - void WillDestroyCurrentMessageLoop() override; - - // MemoryDumpProvider implementation. - bool OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) override; - - void FlushWhileLocked(); - - void CheckThisIsCurrentBuffer() const { - DCHECK(trace_log_->thread_local_event_buffer_.Get() == this); - } - - // Since TraceLog is a leaky singleton, trace_log_ will always be valid - // as long as the thread exists. - TraceLog* trace_log_; - std::unique_ptr<TraceBufferChunk> chunk_; - size_t chunk_index_; - int generation_; - - DISALLOW_COPY_AND_ASSIGN(ThreadLocalEventBuffer); -}; - -TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log) - : trace_log_(trace_log), - chunk_index_(0), - generation_(trace_log->generation()) { - // ThreadLocalEventBuffer is created only if the thread has a message loop, so - // the following message_loop won't be NULL. - MessageLoop* message_loop = MessageLoop::current(); - message_loop->AddDestructionObserver(this); - - // This is to report the local memory usage when memory-infra is enabled. - MemoryDumpManager::GetInstance()->RegisterDumpProvider( - this, "ThreadLocalEventBuffer", ThreadTaskRunnerHandle::Get()); - - AutoLock lock(trace_log->lock_); - trace_log->thread_message_loops_.insert(message_loop); -} - -TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { - CheckThisIsCurrentBuffer(); - MessageLoop::current()->RemoveDestructionObserver(this); - MemoryDumpManager::GetInstance()->UnregisterDumpProvider(this); - - { - AutoLock lock(trace_log_->lock_); - FlushWhileLocked(); - trace_log_->thread_message_loops_.erase(MessageLoop::current()); - } - trace_log_->thread_local_event_buffer_.Set(nullptr); -} - -TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( - TraceEventHandle* handle) { - CheckThisIsCurrentBuffer(); - - if (chunk_ && chunk_->IsFull()) { - AutoLock lock(trace_log_->lock_); - FlushWhileLocked(); - chunk_.reset(); - } - if (!chunk_) { - AutoLock lock(trace_log_->lock_); - chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_); - trace_log_->CheckIfBufferIsFullWhileLocked(); - } - if (!chunk_) - return nullptr; - - size_t event_index; - TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index); - if (trace_event && handle) - MakeHandle(chunk_->seq(), chunk_index_, event_index, handle); - - return trace_event; -} - -void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() { - delete this; -} - -bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) { - if (!chunk_) - return true; - std::string dump_base_name = StringPrintf( - "tracing/thread_%d", static_cast<int>(PlatformThread::CurrentId())); - TraceEventMemoryOverhead overhead; - chunk_->EstimateTraceMemoryOverhead(&overhead); - overhead.DumpInto(dump_base_name.c_str(), pmd); - return true; -} - -void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() { - if (!chunk_) - return; - - trace_log_->lock_.AssertAcquired(); - if (trace_log_->CheckGeneration(generation_)) { - // Return the chunk to the buffer only if the generation matches. - trace_log_->logged_events_->ReturnChunk(chunk_index_, std::move(chunk_)); - } - // Otherwise this method may be called from the destructor, or TraceLog will - // find the generation mismatch and delete this buffer soon. -} - -void TraceLog::SetAddTraceEventOverride( - const AddTraceEventOverrideCallback& override) { - subtle::NoBarrier_Store(&trace_event_override_, - reinterpret_cast<subtle::AtomicWord>(override)); -} - -struct TraceLog::RegisteredAsyncObserver { - explicit RegisteredAsyncObserver(WeakPtr<AsyncEnabledStateObserver> observer) - : observer(observer), task_runner(ThreadTaskRunnerHandle::Get()) {} - ~RegisteredAsyncObserver() = default; - - WeakPtr<AsyncEnabledStateObserver> observer; - scoped_refptr<SequencedTaskRunner> task_runner; -}; - -TraceLogStatus::TraceLogStatus() : event_capacity(0), event_count(0) {} - -TraceLogStatus::~TraceLogStatus() = default; - -// static -TraceLog* TraceLog::GetInstance() { - static base::NoDestructor<TraceLog> instance; - return instance.get(); -} - -// static -void TraceLog::ResetForTesting() { - if (!g_trace_log_for_testing) - return; - CategoryRegistry::ResetForTesting(); - g_trace_log_for_testing->~TraceLog(); - new (g_trace_log_for_testing) TraceLog; -} - -TraceLog::TraceLog() - : enabled_modes_(0), - num_traces_recorded_(0), - dispatching_to_observer_list_(false), - process_sort_index_(0), - process_id_hash_(0), - process_id_(0), - trace_options_(kInternalRecordUntilFull), - trace_config_(TraceConfig()), - thread_shared_chunk_index_(0), - generation_(0), - use_worker_thread_(false), - trace_event_override_(0), - filter_factory_for_testing_(nullptr) { - CategoryRegistry::Initialize(); - -#if defined(OS_NACL) // NaCl shouldn't expose the process id. - SetProcessID(0); -#else - SetProcessID(static_cast<int>(GetCurrentProcId())); -#endif - -// Linux renderer processes and Android O processes are not allowed to read -// "proc/stat" file, crbug.com/788870. -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - process_creation_time_ = CurrentProcessInfo::CreationTime(); -#else - // Use approximate time when creation time is not available. - process_creation_time_ = TRACE_TIME_NOW(); -#endif - - logged_events_.reset(CreateTraceBuffer()); - - MemoryDumpManager::GetInstance()->RegisterDumpProvider(this, "TraceLog", - nullptr); - g_trace_log_for_testing = this; -} - -TraceLog::~TraceLog() = default; - -void TraceLog::InitializeThreadLocalEventBufferIfSupported() { - // A ThreadLocalEventBuffer needs the message loop - // - to know when the thread exits; - // - to handle the final flush. - // For a thread without a message loop or the message loop may be blocked, the - // trace events will be added into the main buffer directly. - if (thread_blocks_message_loop_.Get() || !MessageLoopCurrent::IsSet()) - return; - HEAP_PROFILER_SCOPED_IGNORE; - auto* thread_local_event_buffer = thread_local_event_buffer_.Get(); - if (thread_local_event_buffer && - !CheckGeneration(thread_local_event_buffer->generation())) { - delete thread_local_event_buffer; - thread_local_event_buffer = nullptr; - } - if (!thread_local_event_buffer) { - thread_local_event_buffer = new ThreadLocalEventBuffer(this); - thread_local_event_buffer_.Set(thread_local_event_buffer); - } -} - -bool TraceLog::OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) { - // TODO(ssid): Use MemoryDumpArgs to create light dumps when requested - // (crbug.com/499731). - TraceEventMemoryOverhead overhead; - overhead.Add(TraceEventMemoryOverhead::kOther, sizeof(*this)); - { - AutoLock lock(lock_); - if (logged_events_) - logged_events_->EstimateTraceMemoryOverhead(&overhead); - - for (auto& metadata_event : metadata_events_) - metadata_event->EstimateTraceMemoryOverhead(&overhead); - } - overhead.AddSelf(); - overhead.DumpInto("tracing/main_trace_log", pmd); - return true; -} - -const unsigned char* TraceLog::GetCategoryGroupEnabled( - const char* category_group) { - TraceLog* tracelog = GetInstance(); - if (!tracelog) { - DCHECK(!CategoryRegistry::kCategoryAlreadyShutdown->is_enabled()); - return CategoryRegistry::kCategoryAlreadyShutdown->state_ptr(); - } - TraceCategory* category = CategoryRegistry::GetCategoryByName(category_group); - if (!category) { - // Slow path: in the case of a new category we have to repeat the check - // holding the lock, as multiple threads might have reached this point - // at the same time. - auto category_initializer = [](TraceCategory* category) { - TraceLog::GetInstance()->UpdateCategoryState(category); - }; - AutoLock lock(tracelog->lock_); - CategoryRegistry::GetOrCreateCategoryLocked( - category_group, category_initializer, &category); - } - DCHECK(category->state_ptr()); - return category->state_ptr(); -} - -const char* TraceLog::GetCategoryGroupName( - const unsigned char* category_group_enabled) { - return CategoryRegistry::GetCategoryByStatePtr(category_group_enabled) - ->name(); -} - -void TraceLog::UpdateCategoryState(TraceCategory* category) { - lock_.AssertAcquired(); - DCHECK(category->is_valid()); - unsigned char state_flags = 0; - if (enabled_modes_ & RECORDING_MODE && - trace_config_.IsCategoryGroupEnabled(category->name())) { - state_flags |= TraceCategory::ENABLED_FOR_RECORDING; - } - - // TODO(primiano): this is a temporary workaround for catapult:#2341, - // to guarantee that metadata events are always added even if the category - // filter is "-*". See crbug.com/618054 for more details and long-term fix. - if (enabled_modes_ & RECORDING_MODE && - category == CategoryRegistry::kCategoryMetadata) { - state_flags |= TraceCategory::ENABLED_FOR_RECORDING; - } - - uint32_t enabled_filters_bitmap = 0; - int index = 0; - for (const auto& event_filter : enabled_event_filters_) { - if (event_filter.IsCategoryGroupEnabled(category->name())) { - state_flags |= TraceCategory::ENABLED_FOR_FILTERING; - DCHECK(GetCategoryGroupFilters()[index]); - enabled_filters_bitmap |= 1 << index; - } - if (index++ >= MAX_TRACE_EVENT_FILTERS) { - NOTREACHED(); - break; - } - } - category->set_enabled_filters(enabled_filters_bitmap); - category->set_state(state_flags); -} - -void TraceLog::UpdateCategoryRegistry() { - lock_.AssertAcquired(); - CreateFiltersForTraceConfig(); - for (TraceCategory& category : CategoryRegistry::GetAllCategories()) { - UpdateCategoryState(&category); - } -} - -void TraceLog::CreateFiltersForTraceConfig() { - if (!(enabled_modes_ & FILTERING_MODE)) - return; - - // Filters were already added and tracing could be enabled. Filters list - // cannot be changed when trace events are using them. - if (GetCategoryGroupFilters().size()) - return; - - for (auto& filter_config : enabled_event_filters_) { - if (GetCategoryGroupFilters().size() >= MAX_TRACE_EVENT_FILTERS) { - NOTREACHED() - << "Too many trace event filters installed in the current session"; - break; - } - - std::unique_ptr<TraceEventFilter> new_filter; - const std::string& predicate_name = filter_config.predicate_name(); - if (predicate_name == EventNameFilter::kName) { - auto whitelist = std::make_unique<std::unordered_set<std::string>>(); - CHECK(filter_config.GetArgAsSet("event_name_whitelist", &*whitelist)); - new_filter = std::make_unique<EventNameFilter>(std::move(whitelist)); - } else if (predicate_name == HeapProfilerEventFilter::kName) { - new_filter = std::make_unique<HeapProfilerEventFilter>(); - } else { - if (filter_factory_for_testing_) - new_filter = filter_factory_for_testing_(predicate_name); - CHECK(new_filter) << "Unknown trace filter " << predicate_name; - } - GetCategoryGroupFilters().push_back(std::move(new_filter)); - } -} - -void TraceLog::GetKnownCategoryGroups( - std::vector<std::string>* category_groups) { - for (const auto& category : CategoryRegistry::GetAllCategories()) { - if (!CategoryRegistry::IsBuiltinCategory(&category)) - category_groups->push_back(category.name()); - } -} - -void TraceLog::SetEnabled(const TraceConfig& trace_config, - uint8_t modes_to_enable) { - std::vector<EnabledStateObserver*> observer_list; - std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> observer_map; - { - AutoLock lock(lock_); - - // Can't enable tracing when Flush() is in progress. - DCHECK(!flush_task_runner_); - - InternalTraceOptions new_options = - GetInternalOptionsFromTraceConfig(trace_config); - - InternalTraceOptions old_options = trace_options(); - - if (dispatching_to_observer_list_) { - // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170. - DLOG(ERROR) - << "Cannot manipulate TraceLog::Enabled state from an observer."; - return; - } - - // Clear all filters from previous tracing session. These filters are not - // cleared at the end of tracing because some threads which hit trace event - // when disabling, could try to use the filters. - if (!enabled_modes_) - GetCategoryGroupFilters().clear(); - - // Update trace config for recording. - const bool already_recording = enabled_modes_ & RECORDING_MODE; - if (modes_to_enable & RECORDING_MODE) { - if (already_recording) { - // TODO(ssid): Stop suporting enabling of RECODING_MODE when already - // enabled crbug.com/625170. - DCHECK_EQ(new_options, old_options) << "Attempting to re-enable " - "tracing with a different set " - "of options."; - trace_config_.Merge(trace_config); - } else { - trace_config_ = trace_config; - } - } - - // Update event filters only if filtering was not enabled. - if (modes_to_enable & FILTERING_MODE && enabled_event_filters_.empty()) { - DCHECK(!trace_config.event_filters().empty()); - enabled_event_filters_ = trace_config.event_filters(); - } - // Keep the |trace_config_| updated with only enabled filters in case anyone - // tries to read it using |GetCurrentTraceConfig| (even if filters are - // empty). - trace_config_.SetEventFilters(enabled_event_filters_); - - enabled_modes_ |= modes_to_enable; - UpdateCategoryRegistry(); - - // Do not notify observers or create trace buffer if only enabled for - // filtering or if recording was already enabled. - if (!(modes_to_enable & RECORDING_MODE) || already_recording) - return; - - if (new_options != old_options) { - subtle::NoBarrier_Store(&trace_options_, new_options); - UseNextTraceBuffer(); - } - - num_traces_recorded_++; - - UpdateCategoryRegistry(); - - dispatching_to_observer_list_ = true; - observer_list = enabled_state_observer_list_; - observer_map = async_observers_; - } - // Notify observers outside the lock in case they trigger trace events. - for (EnabledStateObserver* observer : observer_list) - observer->OnTraceLogEnabled(); - for (const auto& it : observer_map) { - it.second.task_runner->PostTask( - FROM_HERE, BindOnce(&AsyncEnabledStateObserver::OnTraceLogEnabled, - it.second.observer)); - } - - { - AutoLock lock(lock_); - dispatching_to_observer_list_ = false; - } -} - -void TraceLog::SetArgumentFilterPredicate( - const ArgumentFilterPredicate& argument_filter_predicate) { - AutoLock lock(lock_); - DCHECK(!argument_filter_predicate.is_null()); - DCHECK(argument_filter_predicate_.is_null()); - argument_filter_predicate_ = argument_filter_predicate; -} - -TraceLog::InternalTraceOptions TraceLog::GetInternalOptionsFromTraceConfig( - const TraceConfig& config) { - InternalTraceOptions ret = config.IsArgumentFilterEnabled() - ? kInternalEnableArgumentFilter - : kInternalNone; - switch (config.GetTraceRecordMode()) { - case RECORD_UNTIL_FULL: - return ret | kInternalRecordUntilFull; - case RECORD_CONTINUOUSLY: - return ret | kInternalRecordContinuously; - case ECHO_TO_CONSOLE: - return ret | kInternalEchoToConsole; - case RECORD_AS_MUCH_AS_POSSIBLE: - return ret | kInternalRecordAsMuchAsPossible; - } - NOTREACHED(); - return kInternalNone; -} - -TraceConfig TraceLog::GetCurrentTraceConfig() const { - AutoLock lock(lock_); - return trace_config_; -} - -void TraceLog::SetDisabled() { - AutoLock lock(lock_); - SetDisabledWhileLocked(RECORDING_MODE); -} - -void TraceLog::SetDisabled(uint8_t modes_to_disable) { - AutoLock lock(lock_); - SetDisabledWhileLocked(modes_to_disable); -} - -void TraceLog::SetDisabledWhileLocked(uint8_t modes_to_disable) { - lock_.AssertAcquired(); - - if (!(enabled_modes_ & modes_to_disable)) - return; - - if (dispatching_to_observer_list_) { - // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170. - DLOG(ERROR) - << "Cannot manipulate TraceLog::Enabled state from an observer."; - return; - } - - bool is_recording_mode_disabled = - (enabled_modes_ & RECORDING_MODE) && (modes_to_disable & RECORDING_MODE); - enabled_modes_ &= ~modes_to_disable; - - if (modes_to_disable & FILTERING_MODE) - enabled_event_filters_.clear(); - - if (modes_to_disable & RECORDING_MODE) - trace_config_.Clear(); - - UpdateCategoryRegistry(); - - // Add metadata events and notify observers only if recording mode was - // disabled now. - if (!is_recording_mode_disabled) - return; - - AddMetadataEventsWhileLocked(); - - // Remove metadata events so they will not get added to a subsequent trace. - metadata_events_.clear(); - - dispatching_to_observer_list_ = true; - std::vector<EnabledStateObserver*> observer_list = - enabled_state_observer_list_; - std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> observer_map = - async_observers_; - - { - // Dispatch to observers outside the lock in case the observer triggers a - // trace event. - AutoUnlock unlock(lock_); - for (EnabledStateObserver* observer : observer_list) - observer->OnTraceLogDisabled(); - for (const auto& it : observer_map) { - it.second.task_runner->PostTask( - FROM_HERE, BindOnce(&AsyncEnabledStateObserver::OnTraceLogDisabled, - it.second.observer)); - } - } - dispatching_to_observer_list_ = false; -} - -int TraceLog::GetNumTracesRecorded() { - AutoLock lock(lock_); - if (!IsEnabled()) - return -1; - return num_traces_recorded_; -} - -void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) { - AutoLock lock(lock_); - enabled_state_observer_list_.push_back(listener); -} - -void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) { - AutoLock lock(lock_); - std::vector<EnabledStateObserver*>::iterator it = - std::find(enabled_state_observer_list_.begin(), - enabled_state_observer_list_.end(), listener); - if (it != enabled_state_observer_list_.end()) - enabled_state_observer_list_.erase(it); -} - -bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const { - AutoLock lock(lock_); - return ContainsValue(enabled_state_observer_list_, listener); -} - -TraceLogStatus TraceLog::GetStatus() const { - AutoLock lock(lock_); - TraceLogStatus result; - result.event_capacity = static_cast<uint32_t>(logged_events_->Capacity()); - result.event_count = static_cast<uint32_t>(logged_events_->Size()); - return result; -} - -bool TraceLog::BufferIsFull() const { - AutoLock lock(lock_); - return logged_events_->IsFull(); -} - -TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( - TraceEventHandle* handle, - bool check_buffer_is_full) { - lock_.AssertAcquired(); - - if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) { - logged_events_->ReturnChunk(thread_shared_chunk_index_, - std::move(thread_shared_chunk_)); - } - - if (!thread_shared_chunk_) { - thread_shared_chunk_ = - logged_events_->GetChunk(&thread_shared_chunk_index_); - if (check_buffer_is_full) - CheckIfBufferIsFullWhileLocked(); - } - if (!thread_shared_chunk_) - return nullptr; - - size_t event_index; - TraceEvent* trace_event = thread_shared_chunk_->AddTraceEvent(&event_index); - if (trace_event && handle) { - MakeHandle(thread_shared_chunk_->seq(), thread_shared_chunk_index_, - event_index, handle); - } - return trace_event; -} - -void TraceLog::CheckIfBufferIsFullWhileLocked() { - lock_.AssertAcquired(); - if (logged_events_->IsFull()) { - if (buffer_limit_reached_timestamp_.is_null()) { - buffer_limit_reached_timestamp_ = OffsetNow(); - } - SetDisabledWhileLocked(RECORDING_MODE); - } -} - -// Flush() works as the following: -// 1. Flush() is called in thread A whose task runner is saved in -// flush_task_runner_; -// 2. If thread_message_loops_ is not empty, thread A posts task to each message -// loop to flush the thread local buffers; otherwise finish the flush; -// 3. FlushCurrentThread() deletes the thread local event buffer: -// - The last batch of events of the thread are flushed into the main buffer; -// - The message loop will be removed from thread_message_loops_; -// If this is the last message loop, finish the flush; -// 4. If any thread hasn't finish its flush in time, finish the flush. -void TraceLog::Flush(const TraceLog::OutputCallback& cb, - bool use_worker_thread) { - FlushInternal(cb, use_worker_thread, false); -} - -void TraceLog::CancelTracing(const OutputCallback& cb) { - SetDisabled(); - FlushInternal(cb, false, true); -} - -void TraceLog::FlushInternal(const TraceLog::OutputCallback& cb, - bool use_worker_thread, - bool discard_events) { - use_worker_thread_ = use_worker_thread; - if (IsEnabled()) { - // Can't flush when tracing is enabled because otherwise PostTask would - // - generate more trace events; - // - deschedule the calling thread on some platforms causing inaccurate - // timing of the trace events. - scoped_refptr<RefCountedString> empty_result = new RefCountedString; - if (!cb.is_null()) - cb.Run(empty_result, false); - LOG(WARNING) << "Ignored TraceLog::Flush called when tracing is enabled"; - return; - } - - int gen = generation(); - // Copy of thread_message_loops_ to be used without locking. - std::vector<scoped_refptr<SingleThreadTaskRunner>> - thread_message_loop_task_runners; - { - AutoLock lock(lock_); - DCHECK(!flush_task_runner_); - flush_task_runner_ = ThreadTaskRunnerHandle::IsSet() - ? ThreadTaskRunnerHandle::Get() - : nullptr; - DCHECK(thread_message_loops_.empty() || flush_task_runner_); - flush_output_callback_ = cb; - - if (thread_shared_chunk_) { - logged_events_->ReturnChunk(thread_shared_chunk_index_, - std::move(thread_shared_chunk_)); - } - - for (MessageLoop* loop : thread_message_loops_) - thread_message_loop_task_runners.push_back(loop->task_runner()); - } - - if (!thread_message_loop_task_runners.empty()) { - for (auto& task_runner : thread_message_loop_task_runners) { - task_runner->PostTask( - FROM_HERE, BindOnce(&TraceLog::FlushCurrentThread, Unretained(this), - gen, discard_events)); - } - flush_task_runner_->PostDelayedTask( - FROM_HERE, - BindOnce(&TraceLog::OnFlushTimeout, Unretained(this), gen, - discard_events), - TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); - return; - } - - FinishFlush(gen, discard_events); -} - -// Usually it runs on a different thread. -void TraceLog::ConvertTraceEventsToTraceFormat( - std::unique_ptr<TraceBuffer> logged_events, - const OutputCallback& flush_output_callback, - const ArgumentFilterPredicate& argument_filter_predicate) { - if (flush_output_callback.is_null()) - return; - - HEAP_PROFILER_SCOPED_IGNORE; - // The callback need to be called at least once even if there is no events - // to let the caller know the completion of flush. - scoped_refptr<RefCountedString> json_events_str_ptr = new RefCountedString(); - const size_t kReserveCapacity = kTraceEventBufferSizeInBytes * 5 / 4; - json_events_str_ptr->data().reserve(kReserveCapacity); - while (const TraceBufferChunk* chunk = logged_events->NextChunk()) { - for (size_t j = 0; j < chunk->size(); ++j) { - size_t size = json_events_str_ptr->size(); - if (size > kTraceEventBufferSizeInBytes) { - flush_output_callback.Run(json_events_str_ptr, true); - json_events_str_ptr = new RefCountedString(); - json_events_str_ptr->data().reserve(kReserveCapacity); - } else if (size) { - json_events_str_ptr->data().append(",\n"); - } - chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()), - argument_filter_predicate); - } - } - flush_output_callback.Run(json_events_str_ptr, false); -} - -void TraceLog::FinishFlush(int generation, bool discard_events) { - std::unique_ptr<TraceBuffer> previous_logged_events; - OutputCallback flush_output_callback; - ArgumentFilterPredicate argument_filter_predicate; - - if (!CheckGeneration(generation)) - return; - - { - AutoLock lock(lock_); - - previous_logged_events.swap(logged_events_); - UseNextTraceBuffer(); - thread_message_loops_.clear(); - - flush_task_runner_ = nullptr; - flush_output_callback = flush_output_callback_; - flush_output_callback_.Reset(); - - if (trace_options() & kInternalEnableArgumentFilter) { - CHECK(!argument_filter_predicate_.is_null()); - argument_filter_predicate = argument_filter_predicate_; - } - } - - if (discard_events) { - if (!flush_output_callback.is_null()) { - scoped_refptr<RefCountedString> empty_result = new RefCountedString; - flush_output_callback.Run(empty_result, false); - } - return; - } - - if (use_worker_thread_) { - base::PostTaskWithTraits( - FROM_HERE, - {MayBlock(), TaskPriority::BACKGROUND, - TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - BindOnce(&TraceLog::ConvertTraceEventsToTraceFormat, - std::move(previous_logged_events), flush_output_callback, - argument_filter_predicate)); - return; - } - - ConvertTraceEventsToTraceFormat(std::move(previous_logged_events), - flush_output_callback, - argument_filter_predicate); -} - -// Run in each thread holding a local event buffer. -void TraceLog::FlushCurrentThread(int generation, bool discard_events) { - { - AutoLock lock(lock_); - if (!CheckGeneration(generation) || !flush_task_runner_) { - // This is late. The corresponding flush has finished. - return; - } - } - - // This will flush the thread local buffer. - delete thread_local_event_buffer_.Get(); - - // Scheduler uses TRACE_EVENT macros when posting a task, which can lead - // to acquiring a tracing lock. Given that posting a task requires grabbing - // a scheduler lock, we need to post this task outside tracing lock to avoid - // deadlocks. - scoped_refptr<SingleThreadTaskRunner> cached_flush_task_runner; - { - AutoLock lock(lock_); - cached_flush_task_runner = flush_task_runner_; - if (!CheckGeneration(generation) || !flush_task_runner_ || - !thread_message_loops_.empty()) - return; - } - cached_flush_task_runner->PostTask( - FROM_HERE, BindOnce(&TraceLog::FinishFlush, Unretained(this), generation, - discard_events)); -} - -void TraceLog::OnFlushTimeout(int generation, bool discard_events) { - { - AutoLock lock(lock_); - if (!CheckGeneration(generation) || !flush_task_runner_) { - // Flush has finished before timeout. - return; - } - - LOG(WARNING) - << "The following threads haven't finished flush in time. " - "If this happens stably for some thread, please call " - "TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop() from " - "the thread to avoid its trace events from being lost."; - for (hash_set<MessageLoop*>::const_iterator it = - thread_message_loops_.begin(); - it != thread_message_loops_.end(); ++it) { - LOG(WARNING) << "Thread: " << (*it)->GetThreadName(); - } - } - FinishFlush(generation, discard_events); -} - -void TraceLog::UseNextTraceBuffer() { - logged_events_.reset(CreateTraceBuffer()); - subtle::NoBarrier_AtomicIncrement(&generation_, 1); - thread_shared_chunk_.reset(); - thread_shared_chunk_index_ = 0; -} - -TraceEventHandle TraceLog::AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, - trace_event_internal::kNoId, // bind_id - thread_id, - now, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags); -} - -TraceEventHandle TraceLog::AddTraceEventWithBindId( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, - bind_id, - thread_id, - now, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID); -} - -TraceEventHandle TraceLog::AddTraceEventWithProcessId( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int process_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, - trace_event_internal::kNoId, // bind_id - process_id, - now, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID); -} - -// Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp -// with kNoId as bind_id -TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const TimeTicks& timestamp, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, - trace_event_internal::kNoId, // bind_id - thread_id, - timestamp, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags); -} - -TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int thread_id, - const TimeTicks& timestamp, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - TraceEventHandle handle = {0, 0, 0}; - if (!*category_group_enabled) - return handle; - - // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when - // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) -> - // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ... - if (thread_is_in_trace_event_.Get()) - return handle; - - AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_); - - DCHECK(name); - DCHECK(!timestamp.is_null()); - - if (flags & TRACE_EVENT_FLAG_MANGLE_ID) { - if ((flags & TRACE_EVENT_FLAG_FLOW_IN) || - (flags & TRACE_EVENT_FLAG_FLOW_OUT)) - bind_id = MangleEventId(bind_id); - id = MangleEventId(id); - } - - TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp); - ThreadTicks thread_now = ThreadNow(); - - ThreadLocalEventBuffer* thread_local_event_buffer = nullptr; - if (*category_group_enabled & RECORDING_MODE) { - // |thread_local_event_buffer_| can be null if the current thread doesn't - // have a message loop or the message loop is blocked. - InitializeThreadLocalEventBufferIfSupported(); - thread_local_event_buffer = thread_local_event_buffer_.Get(); - } - - // Check and update the current thread name only if the event is for the - // current thread to avoid locks in most cases. - if (thread_id == static_cast<int>(PlatformThread::CurrentId())) { - const char* new_name = - ThreadIdNameManager::GetInstance()->GetName(thread_id); - // Check if the thread name has been set or changed since the previous - // call (if any), but don't bother if the new name is empty. Note this will - // not detect a thread name change within the same char* buffer address: we - // favor common case performance over corner case correctness. - static auto* current_thread_name = new ThreadLocalPointer<const char>(); - if (new_name != current_thread_name->Get() && new_name && *new_name) { - current_thread_name->Set(new_name); - - AutoLock thread_info_lock(thread_info_lock_); - - auto existing_name = thread_names_.find(thread_id); - if (existing_name == thread_names_.end()) { - // This is a new thread id, and a new name. - thread_names_[thread_id] = new_name; - } else { - // This is a thread id that we've seen before, but potentially with a - // new name. - std::vector<StringPiece> existing_names = base::SplitStringPiece( - existing_name->second, ",", base::KEEP_WHITESPACE, - base::SPLIT_WANT_NONEMPTY); - if (!ContainsValue(existing_names, new_name)) { - if (!existing_names.empty()) - existing_name->second.push_back(','); - existing_name->second.append(new_name); - } - } - } - } - - AddTraceEventOverrideCallback trace_event_override = - reinterpret_cast<AddTraceEventOverrideCallback>( - subtle::NoBarrier_Load(&trace_event_override_)); - if (trace_event_override) { - TraceEvent new_trace_event; - // If we have an override in place for events, rather than sending - // them to the tracelog, we don't have a way of going back and updating - // the duration of _COMPLETE events. Instead, we emit separate _BEGIN - // and _END events. - if (phase == TRACE_EVENT_PHASE_COMPLETE) - phase = TRACE_EVENT_PHASE_BEGIN; - - new_trace_event.Initialize(thread_id, offset_event_timestamp, thread_now, - phase, category_group_enabled, name, scope, id, - bind_id, num_args, arg_names, arg_types, - arg_values, convertable_values, flags); - - trace_event_override(new_trace_event); - return handle; - } - - std::string console_message; - std::unique_ptr<TraceEvent> filtered_trace_event; - bool disabled_by_filters = false; - if (*category_group_enabled & TraceCategory::ENABLED_FOR_FILTERING) { - std::unique_ptr<TraceEvent> new_trace_event(new TraceEvent); - new_trace_event->Initialize(thread_id, offset_event_timestamp, thread_now, - phase, category_group_enabled, name, scope, id, - bind_id, num_args, arg_names, arg_types, - arg_values, convertable_values, flags); - - disabled_by_filters = true; - ForEachCategoryFilter( - category_group_enabled, [&new_trace_event, &disabled_by_filters]( - TraceEventFilter* trace_event_filter) { - if (trace_event_filter->FilterTraceEvent(*new_trace_event)) - disabled_by_filters = false; - }); - if (!disabled_by_filters) - filtered_trace_event = std::move(new_trace_event); - } - - // If enabled for recording, the event should be added only if one of the - // filters indicates or category is not enabled for filtering. - if ((*category_group_enabled & TraceCategory::ENABLED_FOR_RECORDING) && - !disabled_by_filters) { - OptionalAutoLock lock(&lock_); - - TraceEvent* trace_event = nullptr; - if (thread_local_event_buffer) { - trace_event = thread_local_event_buffer->AddTraceEvent(&handle); - } else { - lock.EnsureAcquired(); - trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); - } - - if (trace_event) { - if (filtered_trace_event) { - trace_event->MoveFrom(std::move(filtered_trace_event)); - } else { - trace_event->Initialize(thread_id, offset_event_timestamp, thread_now, - phase, category_group_enabled, name, scope, id, - bind_id, num_args, arg_names, arg_types, - arg_values, convertable_values, flags); - } - -#if defined(OS_ANDROID) - trace_event->SendToATrace(); -#endif - } - - if (trace_options() & kInternalEchoToConsole) { - console_message = EventToConsoleMessage( - phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, - timestamp, trace_event); - } - } - - if (!console_message.empty()) - LOG(ERROR) << console_message; - - return handle; -} - -void TraceLog::AddMetadataEvent( - const unsigned char* category_group_enabled, - const char* name, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - HEAP_PROFILER_SCOPED_IGNORE; - std::unique_ptr<TraceEvent> trace_event(new TraceEvent); - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - ThreadTicks thread_now = ThreadNow(); - TimeTicks now = OffsetNow(); - AutoLock lock(lock_); - trace_event->Initialize( - thread_id, now, thread_now, TRACE_EVENT_PHASE_METADATA, - category_group_enabled, name, - trace_event_internal::kGlobalScope, // scope - trace_event_internal::kNoId, // id - trace_event_internal::kNoId, // bind_id - num_args, arg_names, arg_types, arg_values, convertable_values, flags); - metadata_events_.push_back(std::move(trace_event)); -} - -// May be called when a COMPELETE event ends and the unfinished event has been -// recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL). -std::string TraceLog::EventToConsoleMessage(unsigned char phase, - const TimeTicks& timestamp, - TraceEvent* trace_event) { - HEAP_PROFILER_SCOPED_IGNORE; - AutoLock thread_info_lock(thread_info_lock_); - - // The caller should translate TRACE_EVENT_PHASE_COMPLETE to - // TRACE_EVENT_PHASE_BEGIN or TRACE_EVENT_END. - DCHECK(phase != TRACE_EVENT_PHASE_COMPLETE); - - TimeDelta duration; - int thread_id = - trace_event ? trace_event->thread_id() : PlatformThread::CurrentId(); - if (phase == TRACE_EVENT_PHASE_END) { - duration = timestamp - thread_event_start_times_[thread_id].top(); - thread_event_start_times_[thread_id].pop(); - } - - std::string thread_name = thread_names_[thread_id]; - if (thread_colors_.find(thread_name) == thread_colors_.end()) { - size_t next_color = (thread_colors_.size() % 6) + 1; - thread_colors_[thread_name] = next_color; - } - - std::ostringstream log; - log << base::StringPrintf("%s: \x1b[0;3%dm", thread_name.c_str(), - thread_colors_[thread_name]); - - size_t depth = 0; - auto it = thread_event_start_times_.find(thread_id); - if (it != thread_event_start_times_.end()) - depth = it->second.size(); - - for (size_t i = 0; i < depth; ++i) - log << "| "; - - if (trace_event) - trace_event->AppendPrettyPrinted(&log); - if (phase == TRACE_EVENT_PHASE_END) - log << base::StringPrintf(" (%.3f ms)", duration.InMillisecondsF()); - - log << "\x1b[0;m"; - - if (phase == TRACE_EVENT_PHASE_BEGIN) - thread_event_start_times_[thread_id].push(timestamp); - - return log.str(); -} - -void TraceLog::EndFilteredEvent(const unsigned char* category_group_enabled, - const char* name, - TraceEventHandle handle) { - const char* category_name = GetCategoryGroupName(category_group_enabled); - ForEachCategoryFilter( - category_group_enabled, - [name, category_name](TraceEventFilter* trace_event_filter) { - trace_event_filter->EndEvent(category_name, name); - }); -} - -void TraceLog::UpdateTraceEventDuration( - const unsigned char* category_group_enabled, - const char* name, - TraceEventHandle handle) { - char category_group_enabled_local = *category_group_enabled; - if (!category_group_enabled_local) - return; - - UpdateTraceEventDurationExplicit(category_group_enabled, name, handle, - OffsetNow(), ThreadNow()); -} - -void TraceLog::UpdateTraceEventDurationExplicit( - const unsigned char* category_group_enabled, - const char* name, - TraceEventHandle handle, - const TimeTicks& now, - const ThreadTicks& thread_now) { - char category_group_enabled_local = *category_group_enabled; - if (!category_group_enabled_local) - return; - - // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when - // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) -> - // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ... - if (thread_is_in_trace_event_.Get()) - return; - AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_); - - std::string console_message; - if (category_group_enabled_local & TraceCategory::ENABLED_FOR_RECORDING) { - AddTraceEventOverrideCallback trace_event_override = - reinterpret_cast<AddTraceEventOverrideCallback>( - subtle::NoBarrier_Load(&trace_event_override_)); - - // If we send events off to an override instead of the TraceBuffer, - // we don't have way of updating the prior event so we'll emit a - // separate _END event instead. - if (trace_event_override) { - TraceEvent new_trace_event; - new_trace_event.Initialize( - static_cast<int>(base::PlatformThread::CurrentId()), now, thread_now, - TRACE_EVENT_PHASE_END, category_group_enabled, name, - trace_event_internal::kGlobalScope, - trace_event_internal::kNoId /* id */, - trace_event_internal::kNoId /* bind_id */, 0, nullptr, nullptr, - nullptr, nullptr, TRACE_EVENT_FLAG_NONE); - trace_event_override(new_trace_event); - return; - } - - OptionalAutoLock lock(&lock_); - - TraceEvent* trace_event = GetEventByHandleInternal(handle, &lock); - if (trace_event) { - DCHECK(trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE); - // TEMP(oysteine) to debug crbug.com/638744 - if (trace_event->duration().ToInternalValue() != -1) { - DVLOG(1) << "TraceHandle: chunk_seq " << handle.chunk_seq - << ", chunk_index " << handle.chunk_index << ", event_index " - << handle.event_index; - - std::string serialized_event; - trace_event->AppendAsJSON(&serialized_event, ArgumentFilterPredicate()); - DVLOG(1) << "TraceEvent: " << serialized_event; - lock_.AssertAcquired(); - } - - trace_event->UpdateDuration(now, thread_now); -#if defined(OS_ANDROID) - trace_event->SendToATrace(); -#endif - } - - if (trace_options() & kInternalEchoToConsole) { - console_message = - EventToConsoleMessage(TRACE_EVENT_PHASE_END, now, trace_event); - } - } - - if (!console_message.empty()) - LOG(ERROR) << console_message; - - if (category_group_enabled_local & TraceCategory::ENABLED_FOR_FILTERING) - EndFilteredEvent(category_group_enabled, name, handle); -} - -uint64_t TraceLog::MangleEventId(uint64_t id) { - return id ^ process_id_hash_; -} - -void TraceLog::AddMetadataEventsWhileLocked() { - lock_.AssertAcquired(); - - // Move metadata added by |AddMetadataEvent| into the trace log. - while (!metadata_events_.empty()) { - TraceEvent* event = AddEventToThreadSharedChunkWhileLocked(nullptr, false); - event->MoveFrom(std::move(metadata_events_.back())); - metadata_events_.pop_back(); - } - -#if !defined(OS_NACL) // NaCl shouldn't expose the process id. - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), 0, "num_cpus", - "number", base::SysInfo::NumberOfProcessors()); -#endif - - int current_thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - if (process_sort_index_ != 0) { - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), - current_thread_id, "process_sort_index", "sort_index", - process_sort_index_); - } - - if (!process_name_.empty()) { - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), - current_thread_id, "process_name", "name", process_name_); - } - - TimeDelta process_uptime = TRACE_TIME_NOW() - process_creation_time_; - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), current_thread_id, - "process_uptime_seconds", "uptime", process_uptime.InSeconds()); - -#if defined(OS_ANDROID) - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), current_thread_id, - "chrome_library_address", "start_address", - base::StringPrintf("%p", &__executable_start)); -#endif - - if (!process_labels_.empty()) { - std::vector<base::StringPiece> labels; - for (const auto& it : process_labels_) - labels.push_back(it.second); - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), - current_thread_id, "process_labels", "labels", - base::JoinString(labels, ",")); - } - - // Thread sort indices. - for (const auto& it : thread_sort_indices_) { - if (it.second == 0) - continue; - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), it.first, - "thread_sort_index", "sort_index", it.second); - } - - // Thread names. - AutoLock thread_info_lock(thread_info_lock_); - for (const auto& it : thread_names_) { - if (it.second.empty()) - continue; - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), it.first, - "thread_name", "name", it.second); - } - - // If buffer is full, add a metadata record to report this. - if (!buffer_limit_reached_timestamp_.is_null()) { - InitializeMetadataEvent( - AddEventToThreadSharedChunkWhileLocked(nullptr, false), - current_thread_id, "trace_buffer_overflowed", "overflowed_at_ts", - buffer_limit_reached_timestamp_); - } -} - -TraceEvent* TraceLog::GetEventByHandle(TraceEventHandle handle) { - return GetEventByHandleInternal(handle, nullptr); -} - -TraceEvent* TraceLog::GetEventByHandleInternal(TraceEventHandle handle, - OptionalAutoLock* lock) { - if (!handle.chunk_seq) - return nullptr; - - DCHECK(handle.chunk_seq); - DCHECK(handle.chunk_index <= TraceBufferChunk::kMaxChunkIndex); - DCHECK(handle.event_index <= TraceBufferChunk::kTraceBufferChunkSize - 1); - - if (thread_local_event_buffer_.Get()) { - TraceEvent* trace_event = - thread_local_event_buffer_.Get()->GetEventByHandle(handle); - if (trace_event) - return trace_event; - } - - // The event has been out-of-control of the thread local buffer. - // Try to get the event from the main buffer with a lock. - if (lock) - lock->EnsureAcquired(); - - if (thread_shared_chunk_ && - handle.chunk_index == thread_shared_chunk_index_) { - return handle.chunk_seq == thread_shared_chunk_->seq() - ? thread_shared_chunk_->GetEventAt(handle.event_index) - : nullptr; - } - - return logged_events_->GetEventByHandle(handle); -} - -void TraceLog::SetProcessID(int process_id) { - process_id_ = process_id; - // Create a FNV hash from the process ID for XORing. - // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details. - const unsigned long long kOffsetBasis = 14695981039346656037ull; - const unsigned long long kFnvPrime = 1099511628211ull; - const unsigned long long pid = static_cast<unsigned long long>(process_id_); - process_id_hash_ = (kOffsetBasis ^ pid) * kFnvPrime; -} - -void TraceLog::SetProcessSortIndex(int sort_index) { - AutoLock lock(lock_); - process_sort_index_ = sort_index; -} - -void TraceLog::UpdateProcessLabel(int label_id, - const std::string& current_label) { - if (!current_label.length()) - return RemoveProcessLabel(label_id); - - AutoLock lock(lock_); - process_labels_[label_id] = current_label; -} - -void TraceLog::RemoveProcessLabel(int label_id) { - AutoLock lock(lock_); - process_labels_.erase(label_id); -} - -void TraceLog::SetThreadSortIndex(PlatformThreadId thread_id, int sort_index) { - AutoLock lock(lock_); - thread_sort_indices_[static_cast<int>(thread_id)] = sort_index; -} - -void TraceLog::SetTimeOffset(TimeDelta offset) { - time_offset_ = offset; -} - -size_t TraceLog::GetObserverCountForTest() const { - return enabled_state_observer_list_.size(); -} - -void TraceLog::SetCurrentThreadBlocksMessageLoop() { - thread_blocks_message_loop_.Set(true); - // This will flush the thread local buffer. - delete thread_local_event_buffer_.Get(); -} - -TraceBuffer* TraceLog::CreateTraceBuffer() { - HEAP_PROFILER_SCOPED_IGNORE; - InternalTraceOptions options = trace_options(); - if (options & kInternalRecordContinuously) { - return TraceBuffer::CreateTraceBufferRingBuffer( - kTraceEventRingBufferChunks); - } - if (options & kInternalEchoToConsole) { - return TraceBuffer::CreateTraceBufferRingBuffer( - kEchoToConsoleTraceEventBufferChunks); - } - if (options & kInternalRecordAsMuchAsPossible) { - return TraceBuffer::CreateTraceBufferVectorOfSize( - kTraceEventVectorBigBufferChunks); - } - return TraceBuffer::CreateTraceBufferVectorOfSize( - kTraceEventVectorBufferChunks); -} - -void TraceLog::SetTraceBufferForTesting( - std::unique_ptr<TraceBuffer> trace_buffer) { - AutoLock lock(lock_); - logged_events_ = std::move(trace_buffer); -} - -void ConvertableToTraceFormat::EstimateTraceMemoryOverhead( - TraceEventMemoryOverhead* overhead) { - overhead->Add(TraceEventMemoryOverhead::kConvertableToTraceFormat, - sizeof(*this)); -} - -void TraceLog::AddAsyncEnabledStateObserver( - WeakPtr<AsyncEnabledStateObserver> listener) { - AutoLock lock(lock_); - async_observers_.insert( - std::make_pair(listener.get(), RegisteredAsyncObserver(listener))); -} - -void TraceLog::RemoveAsyncEnabledStateObserver( - AsyncEnabledStateObserver* listener) { - AutoLock lock(lock_); - async_observers_.erase(listener); -} - -bool TraceLog::HasAsyncEnabledStateObserver( - AsyncEnabledStateObserver* listener) const { - AutoLock lock(lock_); - return ContainsKey(async_observers_, listener); -} - -} // namespace trace_event -} // namespace base - -namespace trace_event_internal { - -ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( - const char* category_group, - const char* name) { - // The single atom works because for now the category_group can only be "gpu". - DCHECK_EQ(strcmp(category_group, "gpu"), 0); - static TRACE_EVENT_API_ATOMIC_WORD atomic = 0; - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( - category_group, atomic, category_group_enabled_); - name_ = name; - if (*category_group_enabled_) { - event_handle_ = - TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - TRACE_EVENT_PHASE_COMPLETE, category_group_enabled_, name, - trace_event_internal::kGlobalScope, // scope - trace_event_internal::kNoId, // id - static_cast<int>(base::PlatformThread::CurrentId()), // thread_id - TRACE_TIME_TICKS_NOW(), trace_event_internal::kZeroNumArgs, nullptr, - nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_NONE); - } -} - -ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { - if (*category_group_enabled_) { - TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, - event_handle_); - } -} - -} // namespace trace_event_internal
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h deleted file mode 100644 index e480323..0000000 --- a/base/trace_event/trace_log.h +++ /dev/null
@@ -1,521 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_LOG_H_ -#define BASE_TRACE_EVENT_TRACE_LOG_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <memory> -#include <string> -#include <unordered_map> -#include <vector> - -#include "base/atomicops.h" -#include "base/containers/stack.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/time/time_override.h" -#include "base/trace_event/memory_dump_provider.h" -#include "base/trace_event/trace_config.h" -#include "base/trace_event/trace_event_impl.h" -#include "build_config.h" - -namespace base { - -class MessageLoop; -class RefCountedString; - -template <typename T> -class NoDestructor; - -namespace trace_event { - -struct TraceCategory; -class TraceBuffer; -class TraceBufferChunk; -class TraceEvent; -class TraceEventFilter; -class TraceEventMemoryOverhead; - -struct BASE_EXPORT TraceLogStatus { - TraceLogStatus(); - ~TraceLogStatus(); - uint32_t event_capacity; - uint32_t event_count; -}; - -class BASE_EXPORT TraceLog : public MemoryDumpProvider { - public: - // Argument passed to TraceLog::SetEnabled. - enum Mode : uint8_t { - // Enables normal tracing (recording trace events in the trace buffer). - RECORDING_MODE = 1 << 0, - - // Trace events are enabled just for filtering but not for recording. Only - // event filters config of |trace_config| argument is used. - FILTERING_MODE = 1 << 1 - }; - - static TraceLog* GetInstance(); - - // Get set of known category groups. This can change as new code paths are - // reached. The known category groups are inserted into |category_groups|. - void GetKnownCategoryGroups(std::vector<std::string>* category_groups); - - // Retrieves a copy (for thread-safety) of the current TraceConfig. - TraceConfig GetCurrentTraceConfig() const; - - // Initializes the thread-local event buffer, if not already initialized and - // if the current thread supports that (has a message loop). - void InitializeThreadLocalEventBufferIfSupported(); - - // See TraceConfig comments for details on how to control which categories - // will be traced. SetDisabled must be called distinctly for each mode that is - // enabled. If tracing has already been enabled for recording, category filter - // (enabled and disabled categories) will be merged into the current category - // filter. Enabling RECORDING_MODE does not enable filters. Trace event - // filters will be used only if FILTERING_MODE is set on |modes_to_enable|. - // Conversely to RECORDING_MODE, FILTERING_MODE doesn't support upgrading, - // i.e. filters can only be enabled if not previously enabled. - void SetEnabled(const TraceConfig& trace_config, uint8_t modes_to_enable); - - // TODO(ssid): Remove the default SetEnabled and IsEnabled. They should take - // Mode as argument. - - // Disables tracing for all categories for the specified |modes_to_disable| - // only. Only RECORDING_MODE is taken as default |modes_to_disable|. - void SetDisabled(); - void SetDisabled(uint8_t modes_to_disable); - - // Returns true if TraceLog is enabled on recording mode. - // Note: Returns false even if FILTERING_MODE is enabled. - bool IsEnabled() { return enabled_modes_ & RECORDING_MODE; } - - // Returns a bitmap of enabled modes from TraceLog::Mode. - uint8_t enabled_modes() { return enabled_modes_; } - - // The number of times we have begun recording traces. If tracing is off, - // returns -1. If tracing is on, then it returns the number of times we have - // recorded a trace. By watching for this number to increment, you can - // passively discover when a new trace has begun. This is then used to - // implement the TRACE_EVENT_IS_NEW_TRACE() primitive. - int GetNumTracesRecorded(); - -#if defined(OS_ANDROID) - void StartATrace(); - void StopATrace(); - void AddClockSyncMetadataEvent(); -#endif - - // Enabled state listeners give a callback when tracing is enabled or - // disabled. This can be used to tie into other library's tracing systems - // on-demand. - class BASE_EXPORT EnabledStateObserver { - public: - virtual ~EnabledStateObserver() = default; - - // Called just after the tracing system becomes enabled, outside of the - // |lock_|. TraceLog::IsEnabled() is true at this point. - virtual void OnTraceLogEnabled() = 0; - - // Called just after the tracing system disables, outside of the |lock_|. - // TraceLog::IsEnabled() is false at this point. - virtual void OnTraceLogDisabled() = 0; - }; - void AddEnabledStateObserver(EnabledStateObserver* listener); - void RemoveEnabledStateObserver(EnabledStateObserver* listener); - bool HasEnabledStateObserver(EnabledStateObserver* listener) const; - - // Asynchronous enabled state listeners. When tracing is enabled or disabled, - // for each observer, a task for invoking its appropriate callback is posted - // to the thread from which AddAsyncEnabledStateObserver() was called. This - // allows the observer to be safely destroyed, provided that it happens on the - // same thread that invoked AddAsyncEnabledStateObserver(). - class BASE_EXPORT AsyncEnabledStateObserver { - public: - virtual ~AsyncEnabledStateObserver() = default; - - // Posted just after the tracing system becomes enabled, outside |lock_|. - // TraceLog::IsEnabled() is true at this point. - virtual void OnTraceLogEnabled() = 0; - - // Posted just after the tracing system becomes disabled, outside |lock_|. - // TraceLog::IsEnabled() is false at this point. - virtual void OnTraceLogDisabled() = 0; - }; - void AddAsyncEnabledStateObserver( - WeakPtr<AsyncEnabledStateObserver> listener); - void RemoveAsyncEnabledStateObserver(AsyncEnabledStateObserver* listener); - bool HasAsyncEnabledStateObserver(AsyncEnabledStateObserver* listener) const; - - TraceLogStatus GetStatus() const; - bool BufferIsFull() const; - - // Computes an estimate of the size of the TraceLog including all the retained - // objects. - void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); - - void SetArgumentFilterPredicate( - const ArgumentFilterPredicate& argument_filter_predicate); - - // Flush all collected events to the given output callback. The callback will - // be called one or more times either synchronously or asynchronously from - // the current thread with IPC-bite-size chunks. The string format is - // undefined. Use TraceResultBuffer to convert one or more trace strings to - // JSON. The callback can be null if the caller doesn't want any data. - // Due to the implementation of thread-local buffers, flush can't be - // done when tracing is enabled. If called when tracing is enabled, the - // callback will be called directly with (empty_string, false) to indicate - // the end of this unsuccessful flush. Flush does the serialization - // on the same thread if the caller doesn't set use_worker_thread explicitly. - typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&, - bool has_more_events)> OutputCallback; - void Flush(const OutputCallback& cb, bool use_worker_thread = false); - - // Cancels tracing and discards collected data. - void CancelTracing(const OutputCallback& cb); - - typedef void (*AddTraceEventOverrideCallback)(const TraceEvent&); - // The callback will be called up until the point where the flush is - // finished, i.e. must be callable until OutputCallback is called with - // has_more_events==false. - void SetAddTraceEventOverride(const AddTraceEventOverrideCallback& override); - - // Called by TRACE_EVENT* macros, don't call this directly. - // The name parameter is a category group for example: - // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent") - static const unsigned char* GetCategoryGroupEnabled(const char* name); - static const char* GetCategoryGroupName( - const unsigned char* category_group_enabled); - - // Called by TRACE_EVENT* macros, don't call this directly. - // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied - // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above. - TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); - TraceEventHandle AddTraceEventWithBindId( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); - TraceEventHandle AddTraceEventWithProcessId( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int process_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); - TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const TimeTicks& timestamp, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); - TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int thread_id, - const TimeTicks& timestamp, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); - - // Adds a metadata event that will be written when the trace log is flushed. - void AddMetadataEvent( - const unsigned char* category_group_enabled, - const char* name, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); - - void UpdateTraceEventDuration(const unsigned char* category_group_enabled, - const char* name, - TraceEventHandle handle); - - void UpdateTraceEventDurationExplicit( - const unsigned char* category_group_enabled, - const char* name, - TraceEventHandle handle, - const TimeTicks& now, - const ThreadTicks& thread_now); - - void EndFilteredEvent(const unsigned char* category_group_enabled, - const char* name, - TraceEventHandle handle); - - int process_id() const { return process_id_; } - - uint64_t MangleEventId(uint64_t id); - - // Exposed for unittesting: - - // Testing factory for TraceEventFilter. - typedef std::unique_ptr<TraceEventFilter> (*FilterFactoryForTesting)( - const std::string& /* predicate_name */); - void SetFilterFactoryForTesting(FilterFactoryForTesting factory) { - filter_factory_for_testing_ = factory; - } - - // Allows clearing up our singleton instance. - static void ResetForTesting(); - - // Allow tests to inspect TraceEvents. - TraceEvent* GetEventByHandle(TraceEventHandle handle); - - void SetProcessID(int process_id); - - // Process sort indices, if set, override the order of a process will appear - // relative to other processes in the trace viewer. Processes are sorted first - // on their sort index, ascending, then by their name, and then tid. - void SetProcessSortIndex(int sort_index); - - // Sets the name of the process. - void set_process_name(const std::string& process_name) { - AutoLock lock(lock_); - process_name_ = process_name; - } - - bool IsProcessNameEmpty() const { return process_name_.empty(); } - - // Processes can have labels in addition to their names. Use labels, for - // instance, to list out the web page titles that a process is handling. - void UpdateProcessLabel(int label_id, const std::string& current_label); - void RemoveProcessLabel(int label_id); - - // Thread sort indices, if set, override the order of a thread will appear - // within its process in the trace viewer. Threads are sorted first on their - // sort index, ascending, then by their name, and then tid. - void SetThreadSortIndex(PlatformThreadId thread_id, int sort_index); - - // Allow setting an offset between the current TimeTicks time and the time - // that should be reported. - void SetTimeOffset(TimeDelta offset); - - size_t GetObserverCountForTest() const; - - // Call this method if the current thread may block the message loop to - // prevent the thread from using the thread-local buffer because the thread - // may not handle the flush request in time causing lost of unflushed events. - void SetCurrentThreadBlocksMessageLoop(); - - // Replaces |logged_events_| with a new TraceBuffer for testing. - void SetTraceBufferForTesting(std::unique_ptr<TraceBuffer> trace_buffer); - - private: - typedef unsigned int InternalTraceOptions; - - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceBufferRingBufferGetReturnChunk); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceBufferRingBufferHalfIteration); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceBufferRingBufferFullIteration); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, TraceBufferVectorReportFull); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - ConvertTraceConfigToInternalOptions); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceRecordAsMuchAsPossibleMode); - - friend class base::NoDestructor<TraceLog>; - - // MemoryDumpProvider implementation. - bool OnMemoryDump(const MemoryDumpArgs& args, - ProcessMemoryDump* pmd) override; - - // Enable/disable each category group based on the current mode_, - // category_filter_ and event_filters_enabled_. - // Enable the category group in the recording mode if category_filter_ matches - // the category group, is not null. Enable category for filtering if any - // filter in event_filters_enabled_ enables it. - void UpdateCategoryRegistry(); - void UpdateCategoryState(TraceCategory* category); - - void CreateFiltersForTraceConfig(); - - InternalTraceOptions GetInternalOptionsFromTraceConfig( - const TraceConfig& config); - - class ThreadLocalEventBuffer; - class OptionalAutoLock; - struct RegisteredAsyncObserver; - - TraceLog(); - ~TraceLog() override; - void AddMetadataEventsWhileLocked(); - - InternalTraceOptions trace_options() const { - return static_cast<InternalTraceOptions>( - subtle::NoBarrier_Load(&trace_options_)); - } - - TraceBuffer* trace_buffer() const { return logged_events_.get(); } - TraceBuffer* CreateTraceBuffer(); - - std::string EventToConsoleMessage(unsigned char phase, - const TimeTicks& timestamp, - TraceEvent* trace_event); - - TraceEvent* AddEventToThreadSharedChunkWhileLocked(TraceEventHandle* handle, - bool check_buffer_is_full); - void CheckIfBufferIsFullWhileLocked(); - void SetDisabledWhileLocked(uint8_t modes); - - TraceEvent* GetEventByHandleInternal(TraceEventHandle handle, - OptionalAutoLock* lock); - - void FlushInternal(const OutputCallback& cb, - bool use_worker_thread, - bool discard_events); - - // |generation| is used in the following callbacks to check if the callback - // is called for the flush of the current |logged_events_|. - void FlushCurrentThread(int generation, bool discard_events); - // Usually it runs on a different thread. - static void ConvertTraceEventsToTraceFormat( - std::unique_ptr<TraceBuffer> logged_events, - const TraceLog::OutputCallback& flush_output_callback, - const ArgumentFilterPredicate& argument_filter_predicate); - void FinishFlush(int generation, bool discard_events); - void OnFlushTimeout(int generation, bool discard_events); - - int generation() const { - return static_cast<int>(subtle::NoBarrier_Load(&generation_)); - } - bool CheckGeneration(int generation) const { - return generation == this->generation(); - } - void UseNextTraceBuffer(); - - TimeTicks OffsetNow() const { - // This should be TRACE_TIME_TICKS_NOW but include order makes that hard. - return OffsetTimestamp(base::subtle::TimeTicksNowIgnoringOverride()); - } - TimeTicks OffsetTimestamp(const TimeTicks& timestamp) const { - return timestamp - time_offset_; - } - - // Internal representation of trace options since we store the currently used - // trace option as an AtomicWord. - static const InternalTraceOptions kInternalNone; - static const InternalTraceOptions kInternalRecordUntilFull; - static const InternalTraceOptions kInternalRecordContinuously; - static const InternalTraceOptions kInternalEchoToConsole; - static const InternalTraceOptions kInternalRecordAsMuchAsPossible; - static const InternalTraceOptions kInternalEnableArgumentFilter; - - // This lock protects TraceLog member accesses (except for members protected - // by thread_info_lock_) from arbitrary threads. - mutable Lock lock_; - // This lock protects accesses to thread_names_, thread_event_start_times_ - // and thread_colors_. - Lock thread_info_lock_; - uint8_t enabled_modes_; // See TraceLog::Mode. - int num_traces_recorded_; - std::unique_ptr<TraceBuffer> logged_events_; - std::vector<std::unique_ptr<TraceEvent>> metadata_events_; - bool dispatching_to_observer_list_; - std::vector<EnabledStateObserver*> enabled_state_observer_list_; - std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> - async_observers_; - - std::string process_name_; - std::unordered_map<int, std::string> process_labels_; - int process_sort_index_; - std::unordered_map<int, int> thread_sort_indices_; - std::unordered_map<int, std::string> thread_names_; - base::Time process_creation_time_; - - // The following two maps are used only when ECHO_TO_CONSOLE. - std::unordered_map<int, base::stack<TimeTicks>> thread_event_start_times_; - std::unordered_map<std::string, int> thread_colors_; - - TimeTicks buffer_limit_reached_timestamp_; - - // XORed with TraceID to make it unlikely to collide with other processes. - unsigned long long process_id_hash_; - - int process_id_; - - TimeDelta time_offset_; - - subtle::AtomicWord /* Options */ trace_options_; - - TraceConfig trace_config_; - TraceConfig::EventFilters enabled_event_filters_; - - ThreadLocalPointer<ThreadLocalEventBuffer> thread_local_event_buffer_; - ThreadLocalBoolean thread_blocks_message_loop_; - ThreadLocalBoolean thread_is_in_trace_event_; - - // Contains the message loops of threads that have had at least one event - // added into the local event buffer. Not using SingleThreadTaskRunner - // because we need to know the life time of the message loops. - hash_set<MessageLoop*> thread_message_loops_; - - // For events which can't be added into the thread local buffer, e.g. events - // from threads without a message loop. - std::unique_ptr<TraceBufferChunk> thread_shared_chunk_; - size_t thread_shared_chunk_index_; - - // Set when asynchronous Flush is in progress. - OutputCallback flush_output_callback_; - scoped_refptr<SingleThreadTaskRunner> flush_task_runner_; - ArgumentFilterPredicate argument_filter_predicate_; - subtle::AtomicWord generation_; - bool use_worker_thread_; - subtle::AtomicWord trace_event_override_; - - FilterFactoryForTesting filter_factory_for_testing_; - - DISALLOW_COPY_AND_ASSIGN(TraceLog); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_LOG_H_
diff --git a/base/trace_event/trace_log_constants.cc b/base/trace_event/trace_log_constants.cc deleted file mode 100644 index 65dca2e..0000000 --- a/base/trace_event/trace_log_constants.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_log.h" - -namespace base { -namespace trace_event { - -// Constant used by TraceLog's internal implementation of trace_option. -const TraceLog::InternalTraceOptions - TraceLog::kInternalNone = 0; -const TraceLog::InternalTraceOptions - TraceLog::kInternalRecordUntilFull = 1 << 0; -const TraceLog::InternalTraceOptions - TraceLog::kInternalRecordContinuously = 1 << 1; -// 1 << 2 is reserved for the DEPRECATED kInternalEnableSampling. DO NOT USE. -const TraceLog::InternalTraceOptions - TraceLog::kInternalEchoToConsole = 1 << 3; -const TraceLog::InternalTraceOptions - TraceLog::kInternalRecordAsMuchAsPossible = 1 << 4; -const TraceLog::InternalTraceOptions - TraceLog::kInternalEnableArgumentFilter = 1 << 5; - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/tracing_agent.cc b/base/trace_event/tracing_agent.cc deleted file mode 100644 index e48feff..0000000 --- a/base/trace_event/tracing_agent.cc +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/tracing_agent.h" - -namespace base { -namespace trace_event { - -TracingAgent::~TracingAgent() = default; - -bool TracingAgent::SupportsExplicitClockSync() { - return false; -} - -void TracingAgent::RecordClockSyncMarker( - const std::string& sync_id, - RecordClockSyncMarkerCallback callback) { - DCHECK(SupportsExplicitClockSync()); -} - - -} // namespace trace_event -} // namespace base
diff --git a/base/trace_event/tracing_agent.h b/base/trace_event/tracing_agent.h deleted file mode 100644 index f818457..0000000 --- a/base/trace_event/tracing_agent.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACING_AGENT_H_ -#define BASE_TRACE_EVENT_TRACING_AGENT_H_ - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/memory/ref_counted_memory.h" -#include "base/values.h" - -namespace base { - -class TimeTicks; - -namespace trace_event { - -class TraceConfig; - -// A tracing agent is an entity that records its own sort of trace. Each -// tracing method that produces its own trace log should implement this -// interface. All tracing agents must only be controlled by TracingController. -// Some existing examples include TracingControllerImpl for Chrome trace events, -// DebugDaemonClient for CrOs system trace, EtwTracingAgent for Windows system -// trace and PowerTracingAgent for BattOr power trace. -class BASE_EXPORT TracingAgent { - public: - using StartAgentTracingCallback = - base::OnceCallback<void(const std::string& agent_name, bool success)>; - // Passing a null or empty events_str_ptr indicates that no trace data is - // available for the specified agent. - using StopAgentTracingCallback = base::OnceCallback<void( - const std::string& agent_name, - const std::string& events_label, - const scoped_refptr<base::RefCountedString>& events_str_ptr)>; - using RecordClockSyncMarkerCallback = - base::OnceCallback<void(const std::string& sync_id, - const TimeTicks& issue_ts, - const TimeTicks& issue_end_ts)>; - - virtual ~TracingAgent(); - - // Gets the name of the tracing agent. Each tracing agent's name should be - // unique. - virtual std::string GetTracingAgentName() = 0; - - // Gets the trace event label of this tracing agent. The label will be used to - // label this agent's trace when all traces from different tracing agents are - // combined. Multiple tracing agents could have the same label. The tracing - // agents using the same label should not be able to run at the same time. For - // example, ETW on Windows and CrOS system tracing both use - // "systemTraceEvents" as the label. Those two agents never run at the same - // time because they are for different platforms. - virtual std::string GetTraceEventLabel() = 0; - - // Starts tracing on the tracing agent with the trace configuration. - virtual void StartAgentTracing(const TraceConfig& trace_config, - StartAgentTracingCallback callback) = 0; - - // Stops tracing on the tracing agent. The trace data will be passed back to - // the TracingController via the callback. - virtual void StopAgentTracing(StopAgentTracingCallback callback) = 0; - - // Checks if the tracing agent supports explicit clock synchronization. - virtual bool SupportsExplicitClockSync(); - - // Records a clock sync marker issued by another tracing agent. This is only - // used if the tracing agent supports explicit clock synchronization. - // - // Two things need to be done: - // 1. The issuer asks the receiver to record the clock sync marker. - // 2. The issuer records how long the receiver takes to do the recording. - // - // In Chrome, the receiver thread also runs in Chrome and it will talk to the - // real receiver entity, e.g., power monitor or Android device system, via - // different communication methods, e.g., through USB or file reading/writing. - // The 2nd task measures that communication latency. - // - // Having a reliable timing measurement for the 2nd task requires synchronous - // function call without any cross-thread or cross-process activity. However, - // tracing agents in Chrome run in their own threads. Therefore, the issuer - // needs to dedicate the 2nd task to the receiver to take time measurements - // in the receiver thread, and the receiver thread needs to pass them back to - // the issuer in the callback. - // - // The assumption is that the receiver thread knows the issuer's clock, which - // is true in Chrome because all agent threads' clocks are Chrome clock. - virtual void RecordClockSyncMarker(const std::string& sync_id, - RecordClockSyncMarkerCallback callback); -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACING_AGENT_H_
diff --git a/base/values.cc b/base/values.cc index 085f0f0..df12c29 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -18,7 +18,6 @@ #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/trace_event/memory_usage_estimator.h" namespace base { @@ -632,21 +631,6 @@ return *this == *other; } -size_t Value::EstimateMemoryUsage() const { - switch (type_) { - case Type::STRING: - return base::trace_event::EstimateMemoryUsage(string_value_); - case Type::BINARY: - return base::trace_event::EstimateMemoryUsage(binary_value_); - case Type::DICTIONARY: - return base::trace_event::EstimateMemoryUsage(dict_); - case Type::LIST: - return base::trace_event::EstimateMemoryUsage(list_); - default: - return 0; - } -} - void Value::InternalMoveConstructFrom(Value&& that) { type_ = that.type_;
diff --git a/build/gen.py b/build/gen.py index 0534e1a..5b81ca6 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -370,36 +370,6 @@ 'base/time/time.cc', 'base/timer/elapsed_timer.cc', 'base/timer/timer.cc', - 'base/trace_event/category_registry.cc', - 'base/trace_event/event_name_filter.cc', - 'base/trace_event/heap_profiler_allocation_context.cc', - 'base/trace_event/heap_profiler_allocation_context_tracker.cc', - 'base/trace_event/heap_profiler_event_filter.cc', - 'base/trace_event/heap_profiler_heap_dump_writer.cc', - 'base/trace_event/heap_profiler_serialization_state.cc', - 'base/trace_event/heap_profiler_stack_frame_deduplicator.cc', - 'base/trace_event/heap_profiler_type_name_deduplicator.cc', - 'base/trace_event/malloc_dump_provider.cc', - 'base/trace_event/memory_allocator_dump.cc', - 'base/trace_event/memory_allocator_dump_guid.cc', - 'base/trace_event/memory_dump_manager.cc', - 'base/trace_event/memory_dump_provider_info.cc', - 'base/trace_event/memory_dump_request_args.cc', - 'base/trace_event/memory_dump_scheduler.cc', - 'base/trace_event/memory_infra_background_whitelist.cc', - 'base/trace_event/memory_peak_detector.cc', - 'base/trace_event/memory_usage_estimator.cc', - 'base/trace_event/process_memory_dump.cc', - 'base/trace_event/trace_buffer.cc', - 'base/trace_event/trace_config.cc', - 'base/trace_event/trace_config_category_filter.cc', - 'base/trace_event/trace_event_argument.cc', - 'base/trace_event/trace_event_filter.cc', - 'base/trace_event/trace_event_impl.cc', - 'base/trace_event/trace_event_memory_overhead.cc', - 'base/trace_event/trace_log.cc', - 'base/trace_event/trace_log_constants.cc', - 'base/trace_event/tracing_agent.cc', 'base/unguessable_token.cc', 'base/value_iterators.cc', 'base/values.cc',