diff options
author | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-01 23:20:20 +0000 |
---|---|---|
committer | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-01 23:20:20 +0000 |
commit | 33047f18fb4d05e45a6a28e706a605ddccc591f6 (patch) | |
tree | fc79c483b777007677dcbdb843f300e602277978 /content/browser | |
parent | b05df6b03e0d5dc552a96578ea6a8a7e47af407c (diff) | |
download | chromium_src-33047f18fb4d05e45a6a28e706a605ddccc591f6.zip chromium_src-33047f18fb4d05e45a6a28e706a605ddccc591f6.tar.gz chromium_src-33047f18fb4d05e45a6a28e706a605ddccc591f6.tar.bz2 |
Collect profiler stats from all browser child processes.
R=jar
Bug=104770
TEST=about:profiler after lauching a plug-in or GPU should show
tracking data for plugin-gpu processes
Review URL: http://codereview.chromium.org/8588023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112571 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r-- | content/browser/browser_child_process_host.cc | 2 | ||||
-rwxr-xr-x | content/browser/profiler_controller_impl.cc | 149 | ||||
-rwxr-xr-x | content/browser/profiler_controller_impl.h | 56 | ||||
-rwxr-xr-x | content/browser/profiler_message_filter.cc | 46 | ||||
-rwxr-xr-x | content/browser/profiler_message_filter.h | 38 | ||||
-rw-r--r-- | content/browser/renderer_host/render_process_host_impl.cc | 6 |
6 files changed, 297 insertions, 0 deletions
diff --git a/content/browser/browser_child_process_host.cc b/content/browser/browser_child_process_host.cc index 35ed45c..09b77ee 100644 --- a/content/browser/browser_child_process_host.cc +++ b/content/browser/browser_child_process_host.cc @@ -13,6 +13,7 @@ #include "base/process_util.h" #include "base/stl_util.h" #include "base/string_util.h" +#include "content/browser/profiler_message_filter.h" #include "content/browser/renderer_host/resource_message_filter.h" #include "content/browser/trace_message_filter.h" #include "content/common/plugin_messages.h" @@ -68,6 +69,7 @@ BrowserChildProcessHost::BrowserChildProcessHost( #endif disconnect_was_alive_(false) { AddFilter(new TraceMessageFilter); + AddFilter(new ProfilerMessageFilter); g_child_process_list.Get().push_back(this); } diff --git a/content/browser/profiler_controller_impl.cc b/content/browser/profiler_controller_impl.cc new file mode 100755 index 0000000..3bfb12a --- /dev/null +++ b/content/browser/profiler_controller_impl.cc @@ -0,0 +1,149 @@ +// Copyright (c) 2011 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 "content/browser/profiler_controller_impl.h" + +#include "base/bind.h" +#include "base/values.h" +#include "content/browser/browser_child_process_host.h" +#include "content/common/child_process_info.h" +#include "content/common/child_process_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/profiler_subscriber.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/common/process_type.h" + +using content::BrowserThread; + +namespace content { + +content::ProfilerController* content::ProfilerController::GetInstance() { + return ProfilerControllerImpl::GetInstance(); +} + +ProfilerControllerImpl* ProfilerControllerImpl::GetInstance() { + return Singleton<ProfilerControllerImpl>::get(); +} + +ProfilerControllerImpl::ProfilerControllerImpl() : subscriber_(NULL) { +} + +ProfilerControllerImpl::~ProfilerControllerImpl() { +} + +void ProfilerControllerImpl::OnPendingProcesses(int sequence_number, + int pending_processes, + bool end) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (subscriber_) + subscriber_->OnPendingProcesses(sequence_number, pending_processes, end); +} + +void ProfilerControllerImpl::OnProfilerDataCollected( + int sequence_number, + base::DictionaryValue* profiler_data) { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&ProfilerControllerImpl::OnProfilerDataCollected, + base::Unretained(this), + sequence_number, + profiler_data)); + return; + } + + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (subscriber_) + subscriber_->OnProfilerDataCollected(sequence_number, profiler_data); +} + +void ProfilerControllerImpl::Register(ProfilerSubscriber* subscriber) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(!subscriber_); + subscriber_ = subscriber; +} + +void ProfilerControllerImpl::Unregister(ProfilerSubscriber* subscriber) { + if (subscriber == subscriber_) + subscriber_ = NULL; +} + +void ProfilerControllerImpl::GetProfilerDataFromChildProcesses( + int sequence_number) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + int pending_processes = 0; + for (BrowserChildProcessHost::Iterator child_process_host; + !child_process_host.Done(); ++child_process_host) { + const std::string process_type = + content::GetProcessTypeNameInEnglish(child_process_host->type()); + ++pending_processes; + if (!child_process_host->Send(new ChildProcessMsg_GetChildProfilerData( + sequence_number, process_type))) { + --pending_processes; + } + } + + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind( + &ProfilerControllerImpl::OnPendingProcesses, + base::Unretained(this), + sequence_number, + pending_processes, + true)); +} + +void ProfilerControllerImpl::GetProfilerData(int sequence_number) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + int pending_processes = 0; + const std::string render_process_type = + content::GetProcessTypeNameInEnglish(content::PROCESS_TYPE_RENDERER); + + for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); + !it.IsAtEnd(); it.Advance()) { + ++pending_processes; + if (!it.GetCurrentValue()->Send(new ChildProcessMsg_GetChildProfilerData( + sequence_number, render_process_type))) { + --pending_processes; + } + } + OnPendingProcesses(sequence_number, pending_processes, false); + + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&ProfilerControllerImpl::GetProfilerDataFromChildProcesses, + base::Unretained(this), + sequence_number)); +} + +void ProfilerControllerImpl::SetProfilerStatusInChildProcesses(bool enable) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + for (BrowserChildProcessHost::Iterator child_process_host; + !child_process_host.Done(); ++child_process_host) { + child_process_host->Send(new ChildProcessMsg_SetProfilerStatus(enable)); + } +} + +void ProfilerControllerImpl::SetProfilerStatus(bool enable) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&ProfilerControllerImpl::SetProfilerStatusInChildProcesses, + base::Unretained(this), + enable)); + + for (content::RenderProcessHost::iterator it( + content::RenderProcessHost::AllHostsIterator()); + !it.IsAtEnd(); it.Advance()) { + it.GetCurrentValue()->Send(new ChildProcessMsg_SetProfilerStatus(enable)); + } +} +} // namespace content diff --git a/content/browser/profiler_controller_impl.h b/content/browser/profiler_controller_impl.h new file mode 100755 index 0000000..eca522a --- /dev/null +++ b/content/browser/profiler_controller_impl.h @@ -0,0 +1,56 @@ +// Copyright (c) 2011 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 CONTENT_BROWSER_PROFILER_CONTROLLER_IMPL_H_ +#define CONTENT_BROWSER_PROFILER_CONTROLLER_IMPL_H_ + +#include "base/memory/singleton.h" +#include "content/common/content_export.h" +#include "content/public/browser/profiler_controller.h" + +namespace content { + +// ProfilerController's implementation. +class CONTENT_EXPORT ProfilerControllerImpl : public ProfilerController { + public: + static ProfilerControllerImpl* GetInstance(); + + // Normally instantiated when the child process is launched. Only one instance + // should be created per process. + ProfilerControllerImpl(); + virtual ~ProfilerControllerImpl(); + + // Send number of pending processes to subscriber_. |end| is set to true if it + // is the last time. This is called on UI thread. + void OnPendingProcesses(int sequence_number, int pending_processes, bool end); + + // Send profiler_data back to subscriber_. subscriber_ assumes the ownership + // of profiler_data. This is called on UI thread. + void OnProfilerDataCollected(int sequence_number, + base::DictionaryValue* profiler_data); + + // ProfilerController implementation: + virtual void Register(ProfilerSubscriber* subscriber) OVERRIDE; + virtual void Unregister(ProfilerSubscriber* subscriber) OVERRIDE; + virtual void GetProfilerData(int sequence_number) OVERRIDE; + virtual void SetProfilerStatus(bool enable) OVERRIDE; + + private: + friend struct DefaultSingletonTraits<ProfilerControllerImpl>; + + // Contact child processes and get their profiler data. + void GetProfilerDataFromChildProcesses(int sequence_number); + + // Contact child processes and set profiler status to |enable|. + void SetProfilerStatusInChildProcesses(bool enable); + + ProfilerSubscriber* subscriber_; + + DISALLOW_COPY_AND_ASSIGN(ProfilerControllerImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_PROFILER_CONTROLLER_IMPL_H_ + diff --git a/content/browser/profiler_message_filter.cc b/content/browser/profiler_message_filter.cc new file mode 100755 index 0000000..f11b670 --- /dev/null +++ b/content/browser/profiler_message_filter.cc @@ -0,0 +1,46 @@ +// Copyright (c) 2011 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 "content/browser/profiler_message_filter.h" + +#include "base/tracked_objects.h" +#include "base/values.h" +#include "content/browser/profiler_controller_impl.h" +#include "content/common/child_process_messages.h" + +using content::BrowserThread; + +ProfilerMessageFilter::ProfilerMessageFilter() { +} + +ProfilerMessageFilter::~ProfilerMessageFilter() { +} + +void ProfilerMessageFilter::OnChannelConnected(int32 peer_pid) { + BrowserMessageFilter::OnChannelConnected(peer_pid); + + bool enable = tracked_objects::ThreadData::tracking_status(); + Send(new ChildProcessMsg_SetProfilerStatus(enable)); +} + +bool ProfilerMessageFilter::OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(ProfilerMessageFilter, message, *message_was_ok) + IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ChildProfilerData, + OnChildProfilerData) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + return handled; +} + +void ProfilerMessageFilter::OnChildProfilerData( + int sequence_number, + const base::DictionaryValue& profiler_data) { + base::DictionaryValue* dictionary_value = new base::DictionaryValue; + dictionary_value->MergeDictionary(&profiler_data); + // OnProfilerDataCollected assumes the ownership of profiler_data. + content::ProfilerControllerImpl::GetInstance()->OnProfilerDataCollected( + sequence_number, dictionary_value); +} diff --git a/content/browser/profiler_message_filter.h b/content/browser/profiler_message_filter.h new file mode 100755 index 0000000..3790527 --- /dev/null +++ b/content/browser/profiler_message_filter.h @@ -0,0 +1,38 @@ +// Copyright (c) 2011 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 CONTENT_BROWSER_PROFILER_MESSAGE_FILTER_H_ +#define CONTENT_BROWSER_PROFILER_MESSAGE_FILTER_H_ + +#include <string> + +#include "content/browser/browser_message_filter.h" + +namespace base { +class DictionaryValue; +} + +// This class sends and receives profiler messages in the browser process. +class ProfilerMessageFilter : public BrowserMessageFilter { + public: + ProfilerMessageFilter(); + virtual ~ProfilerMessageFilter(); + + // BrowserMessageFilter implementation. + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; + + // BrowserMessageFilter implementation. + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE; + + private: + // Message handlers. + void OnChildProfilerData(int sequence_number, + const base::DictionaryValue& profiler_data); + + DISALLOW_COPY_AND_ASSIGN(ProfilerMessageFilter); +}; + +#endif // CONTENT_BROWSER_PROFILER_MESSAGE_FILTER_H_ + diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index d65edbd..31f2bf7 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -33,6 +33,7 @@ #include "base/sys_info.h" #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" +#include "base/tracked_objects.h" #include "content/browser/appcache/appcache_dispatcher_host.h" #include "content/browser/browser_child_process_host.h" #include "content/browser/browser_context.h" @@ -48,6 +49,7 @@ #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h" #include "content/browser/mime_registry_message_filter.h" #include "content/browser/plugin_service.h" +#include "content/browser/profiler_message_filter.h" #include "content/browser/renderer_host/blob_message_filter.h" #include "content/browser/renderer_host/clipboard_message_filter.h" #include "content/browser/renderer_host/database_message_filter.h" @@ -537,6 +539,7 @@ void RenderProcessHostImpl::CreateMessageFilters() { GetID(), GetBrowserContext()->GetQuotaManager(), content::GetContentClient()->browser()->CreateQuotaPermissionContext())); channel_->AddFilter(new GamepadBrowserMessageFilter); + channel_->AddFilter(new ProfilerMessageFilter()); } int RenderProcessHostImpl::GetNextRoutingID() { @@ -941,6 +944,9 @@ void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) { IPC::Logging::GetInstance()->Enabled())); #endif + bool enable = tracked_objects::ThreadData::tracking_status(); + Send(new ChildProcessMsg_SetProfilerStatus(enable)); + // Make sure the child checks with us before exiting, so that we do not try // to schedule a new navigation in a swapped out and exiting renderer. Send(new ChildProcessMsg_AskBeforeShutdown()); |