Commit 16b3a169 authored by Sadrul Habib Chowdhury's avatar Sadrul Habib Chowdhury Committed by Commit Bot

sampling profiler: Set up startup profiler for renderer.

Set up a startup sampling-profiler for the compositor thread in the
renderer process. Notable changes:
. Callback to the RendererClient when the compositor-thread is created.
  The client uses this callback to set-up the sampling profiler.
. Allow the renderer processes to connect to the browser to report the
  profiler data over mojom. Add the --start-stack-profiler flag to the
  renderer's cmd-line so that it can initiate sampling profiler. Select
  every fifth renderer for collecting the profile data from, so that we
  can still get enough useful data, but don't overburden bandwidth or
  memory usage.

BUG=788808

Change-Id: I478184502a17f4dbb83f03a67a7ef482c92c0a78
Reviewed-on: https://chromium-review.googlesource.com/894848Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarMike Wittman <wittman@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Commit-Queue: Sadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#534235}
parent a09247de
......@@ -3049,6 +3049,10 @@ void ChromeContentBrowserClient::ExposeInterfacesToRenderer(
base::Bind(&rappor::RapporRecorderImpl::Create,
g_browser_process->rappor_service()),
ui_task_runner);
registry->AddInterface(
base::BindRepeating(&metrics::CallStackProfileCollector::Create,
metrics::CallStackProfileParams::RENDERER_PROCESS));
if (NetBenchmarking::CheckBenchmarkingEnabled()) {
Profile* profile =
Profile::FromBrowserContext(render_process_host->GetBrowserContext());
......
......@@ -10,6 +10,7 @@
"chrome::mojom::CacheStatsRecorder",
"chrome::mojom::NetBenchmarking",
"extensions::StashService",
"metrics::mojom::CallStackProfileCollector",
"metrics::mojom::LeakDetector",
"mojom::ModuleEventSink",
"rappor::mojom::RapporRecorder",
......
......@@ -47,6 +47,11 @@ bool IsBrowserProcess() {
return process_type.empty();
}
bool ShouldEnableProfilerForNextRendererProcess() {
// Enable for every N-th renderer process, where N = 5.
return base::RandInt(0, 4) == 0;
}
} // namespace
StackSamplingConfiguration::StackSamplingConfiguration()
......@@ -122,8 +127,13 @@ void StackSamplingConfiguration::AppendCommandLineSwitchForChildProcess(
bool enable =
configuration_ == PROFILE_ENABLED || configuration_ == PROFILE_CONTROL;
if (enable && process_type == switches::kGpuProcess)
if (!enable)
return;
if (process_type == switches::kGpuProcess ||
(process_type == switches::kRendererProcess &&
ShouldEnableProfilerForNextRendererProcess())) {
command_line->AppendSwitch(switches::kStartStackProfiler);
}
}
// static
......
......@@ -15,6 +15,7 @@ include_rules = [
"+components/dom_distiller/core",
"+components/grit",
"+components/guest_view/renderer",
"+components/metrics/child_call_stack_profile_collector.h",
"+components/metrics/leak_detector",
"+components/nacl/common",
"+components/nacl/renderer",
......
......@@ -15,9 +15,11 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics_action.h"
#include "base/profiler/stack_sampling_profiler.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
......@@ -38,6 +40,7 @@
#include "chrome/common/profiling/memlog_allocator_shim.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/secure_origin_whitelist.h"
#include "chrome/common/stack_sampling_configuration.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
......@@ -77,6 +80,7 @@
#include "components/dom_distiller/core/url_constants.h"
#include "components/error_page/common/error.h"
#include "components/error_page/common/localized_error.h"
#include "components/metrics/child_call_stack_profile_collector.h"
#include "components/network_hints/renderer/prescient_networking_dispatcher.h"
#include "components/pdf/renderer/pepper_pdf_host.h"
#include "components/safe_browsing/renderer/threat_dom_details.h"
......@@ -225,6 +229,35 @@ const char kFlashYouTubeRewriteUMA[] = "Plugin.Flash.YouTubeRewrite";
namespace {
base::LazyInstance<metrics::ChildCallStackProfileCollector>::Leaky
g_call_stack_profile_collector = LAZY_INSTANCE_INITIALIZER;
// The profiler object is stored in a SequenceLocalStorageSlot on the compositor
// thread so that it will be destroyed when the compositor thread stops.
base::LazyInstance<base::SequenceLocalStorageSlot<
std::unique_ptr<base::StackSamplingProfiler>>>::Leaky
g_compositor_thread_sampling_profiler = LAZY_INSTANCE_INITIALIZER;
// Starts to profile the compositor thread.
void StartCompositorThreadProfiling() {
StackSamplingConfiguration* config = StackSamplingConfiguration::Get();
if (!config->IsProfilerEnabledForCurrentProcess())
return;
auto profiler_callback =
g_call_stack_profile_collector.Get().GetProfilerCallback(
metrics::CallStackProfileParams(
metrics::CallStackProfileParams::RENDERER_PROCESS,
metrics::CallStackProfileParams::COMPOSITOR_THREAD,
metrics::CallStackProfileParams::PROCESS_STARTUP,
metrics::CallStackProfileParams::MAY_SHUFFLE));
auto profiler = std::make_unique<base::StackSamplingProfiler>(
base::PlatformThread::CurrentId(),
config->GetSamplingParamsForCurrentProcess(), profiler_callback);
profiler->Start();
g_compositor_thread_sampling_profiler.Get().Set(std::move(profiler));
}
void RecordYouTubeRewriteUMA(internal::YouTubeRewriteStatus status) {
UMA_HISTOGRAM_ENUMERATION(internal::kFlashYouTubeRewriteUMA, status,
internal::NUM_PLUGIN_ERROR);
......@@ -1211,6 +1244,21 @@ void ChromeContentRendererClient::PrepareErrorPageInternal(
}
}
void ChromeContentRendererClient::PostCompositorThreadCreated(
base::SingleThreadTaskRunner* compositor_thread_task_runner) {
// Do not start the profiler for extension processes.
if (IsStandaloneExtensionProcess())
return;
metrics::mojom::CallStackProfileCollectorPtr browser_interface;
content::ChildThread::Get()->GetConnector()->BindInterface(
content::mojom::kBrowserServiceName, &browser_interface);
g_call_stack_profile_collector.Get().SetParentProfileCollector(
std::move(browser_interface));
compositor_thread_task_runner->PostTask(
FROM_HERE, base::BindOnce(&StartCompositorThreadProfiling));
}
bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() {
return !IsStandaloneExtensionProcess();
}
......
......@@ -149,6 +149,8 @@ class ChromeContentRendererClient
void DeferMediaLoad(content::RenderFrame* render_frame,
bool has_played_media_before,
const base::Closure& closure) override;
void PostCompositorThreadCreated(
base::SingleThreadTaskRunner* compositor_thread_task_runner) override;
bool RunIdleHandlerWhenWidgetsHidden() override;
bool AllowStoppingWhenProcessBackgrounded() override;
bool AllowPopup() override;
......
......@@ -89,6 +89,9 @@ ContentRendererClient::OverrideSpeechSynthesizer(
return nullptr;
}
void ContentRendererClient::PostCompositorThreadCreated(
base::SingleThreadTaskRunner* compositor_thread_task_runner) {}
bool ContentRendererClient::RunIdleHandlerWhenWidgetsHidden() {
return true;
}
......
......@@ -179,6 +179,11 @@ class CONTENT_EXPORT ContentRendererClient {
virtual std::unique_ptr<blink::WebSpeechSynthesizer>
OverrideSpeechSynthesizer(blink::WebSpeechSynthesizerClient* client);
// Called on the main-thread immediately after the compositor thread is
// created.
virtual void PostCompositorThreadCreated(
base::SingleThreadTaskRunner* compositor_thread_task_runner);
// Returns true if the renderer process should schedule the idle handler when
// all widgets are hidden.
virtual bool RunIdleHandlerWhenWidgetsHidden();
......
......@@ -1192,6 +1192,8 @@ void RenderThreadImpl::InitializeCompositorThread() {
FROM_HERE,
base::BindOnce(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed),
false));
GetContentClient()->renderer()->PostCompositorThreadCreated(
compositor_task_runner_.get());
#if defined(OS_LINUX)
render_message_filter()->SetThreadPriority(compositor_thread_->ThreadId(),
base::ThreadPriority::DISPLAY);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment