• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
GetProfileName()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 
FlushProfilingData()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
ProcessStarted()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
Start()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
Stop()87 void Profiling::Stop() {
88   base::debug::StopProfiling();
89 }
90 
91 // static
BeingProfiled()92 bool Profiling::BeingProfiled() {
93   return base::debug::BeingProfiled();
94 }
95 
96 // static
Toggle()97 void Profiling::Toggle() {
98   if (BeingProfiled())
99     Stop();
100   else
101     Start();
102 }
103 
104 // static
MainMessageLoopStarted()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