Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/common/profiling.h"
      6 
      7 #include "base/at_exit.h"
      8 #include "base/command_line.h"
      9 #include "base/debug/profiler.h"
     10 #include "base/message_loop.h"
     11 #include "base/string_util.h"
     12 #include "chrome/common/chrome_switches.h"
     13 
     14 namespace {
     15 std::string GetProfileName() {
     16   static const char kDefaultProfileName[] = "chrome-profile-{pid}";
     17   static std::string profile_name;
     18 
     19   if (profile_name.empty()) {
     20     const CommandLine& command_line = *CommandLine::ForCurrentProcess();
     21     if (command_line.HasSwitch(switches::kProfilingFile))
     22       profile_name = command_line.GetSwitchValueASCII(switches::kProfilingFile);
     23     else
     24       profile_name = std::string(kDefaultProfileName);
     25     std::string process_type =
     26         command_line.GetSwitchValueASCII(switches::kProcessType);
     27     std::string type = process_type.empty() ?
     28         std::string("browser") : std::string(process_type);
     29     ReplaceSubstringsAfterOffset(&profile_name, 0, "{type}", type.c_str());
     30   }
     31   return profile_name;
     32 }
     33 
     34 void FlushProfilingData() {
     35   static const int kProfilingFlushSeconds = 10;
     36 
     37   if (!Profiling::BeingProfiled())
     38     return;
     39 
     40   base::debug::FlushProfiling();
     41   static int flush_seconds = 0;
     42   if (!flush_seconds) {
     43     const CommandLine& command_line = *CommandLine::ForCurrentProcess();
     44     std::string profiling_flush =
     45         command_line.GetSwitchValueASCII(switches::kProfilingFlush);
     46     if (!profiling_flush.empty()) {
     47       flush_seconds = atoi(profiling_flush.c_str());
     48       DCHECK(flush_seconds > 0);
     49     } else {
     50       flush_seconds = kProfilingFlushSeconds;
     51     }
     52   }
     53   MessageLoop::current()->PostDelayedTask(FROM_HERE,
     54       NewRunnableFunction(FlushProfilingData),
     55       flush_seconds * 1000);
     56 }
     57 
     58 } // namespace
     59 
     60 // static
     61 void Profiling::ProcessStarted() {
     62   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
     63   std::string process_type =
     64       command_line.GetSwitchValueASCII(switches::kProcessType);
     65 
     66   if (command_line.HasSwitch(switches::kProfilingAtStart)) {
     67     std::string process_type_to_start =
     68         command_line.GetSwitchValueASCII(switches::kProfilingAtStart);
     69     if (process_type == process_type_to_start)
     70       Start();
     71   }
     72 }
     73 
     74 // static
     75 void Profiling::Start() {
     76   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
     77   bool flush = command_line.HasSwitch(switches::kProfilingFlush);
     78   base::debug::StartProfiling(GetProfileName());
     79 
     80   // Schedule profile data flushing for single process because it doesn't
     81   // get written out correctly on exit.
     82   if (flush && MessageLoop::current())
     83     FlushProfilingData();
     84 }
     85 
     86 // static
     87 void Profiling::Stop() {
     88   base::debug::StopProfiling();
     89 }
     90 
     91 // static
     92 bool Profiling::BeingProfiled() {
     93   return base::debug::BeingProfiled();
     94 }
     95 
     96 // static
     97 void Profiling::Toggle() {
     98   if (BeingProfiled())
     99     Stop();
    100   else
    101     Start();
    102 }
    103 
    104 // static
    105 void Profiling::MainMessageLoopStarted() {
    106   if (BeingProfiled()) {
    107     const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    108     bool flush = command_line.HasSwitch(switches::kProfilingFlush);
    109     if (flush)
    110       FlushProfilingData();
    111   }
    112 }
    113