// Copyright (c) 2010 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 "chrome/common/profiling.h" #include "base/at_exit.h" #include "base/command_line.h" #include "base/debug/profiler.h" #include "base/message_loop.h" #include "base/string_util.h" #include "chrome/common/chrome_switches.h" namespace { std::string GetProfileName() { static const char kDefaultProfileName[] = "chrome-profile-{pid}"; static std::string profile_name; if (profile_name.empty()) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(switches::kProfilingFile)) profile_name = command_line.GetSwitchValueASCII(switches::kProfilingFile); else profile_name = std::string(kDefaultProfileName); std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType); std::string type = process_type.empty() ? std::string("browser") : std::string(process_type); ReplaceSubstringsAfterOffset(&profile_name, 0, "{type}", type.c_str()); } return profile_name; } void FlushProfilingData() { static const int kProfilingFlushSeconds = 10; if (!Profiling::BeingProfiled()) return; base::debug::FlushProfiling(); static int flush_seconds = 0; if (!flush_seconds) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); std::string profiling_flush = command_line.GetSwitchValueASCII(switches::kProfilingFlush); if (!profiling_flush.empty()) { flush_seconds = atoi(profiling_flush.c_str()); DCHECK(flush_seconds > 0); } else { flush_seconds = kProfilingFlushSeconds; } } MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableFunction(FlushProfilingData), flush_seconds * 1000); } } // namespace // static void Profiling::ProcessStarted() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType); if (command_line.HasSwitch(switches::kProfilingAtStart)) { std::string process_type_to_start = command_line.GetSwitchValueASCII(switches::kProfilingAtStart); if (process_type == process_type_to_start) Start(); } } // static void Profiling::Start() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); bool flush = command_line.HasSwitch(switches::kProfilingFlush); base::debug::StartProfiling(GetProfileName()); // Schedule profile data flushing for single process because it doesn't // get written out correctly on exit. if (flush && MessageLoop::current()) FlushProfilingData(); } // static void Profiling::Stop() { base::debug::StopProfiling(); } // static bool Profiling::BeingProfiled() { return base::debug::BeingProfiled(); } // static void Profiling::Toggle() { if (BeingProfiled()) Stop(); else Start(); } // static void Profiling::MainMessageLoopStarted() { if (BeingProfiled()) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); bool flush = command_line.HasSwitch(switches::kProfilingFlush); if (flush) FlushProfilingData(); } }