Commit 12cd16ac authored by ssid's avatar ssid Committed by Commit Bot

Add experiment param to configure reached code sampling interval

BUG=916263

Change-Id: I2bb13e274d18e1dac5d0a91ac86cbd0cdbf2cc18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2263473
Commit-Queue: ssid <ssid@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Reviewed-by: default avatarTommy Nyquist <nyquist@chromium.org>
Reviewed-by: default avatarEgor Pasko <pasko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#782760}
parent f5f8d99b
...@@ -30,6 +30,10 @@ public abstract class BaseSwitches { ...@@ -30,6 +30,10 @@ public abstract class BaseSwitches {
// Enables the reached code profiler. // Enables the reached code profiler.
public static final String ENABLE_REACHED_CODE_PROFILER = "enable-reached-code-profiler"; public static final String ENABLE_REACHED_CODE_PROFILER = "enable-reached-code-profiler";
// Specifies the profiling interval for reached code profiler in microseconds.
public static final String REACHED_CODE_SAMPLING_INTERVAL_US =
"reached-code-sampling-interval-us";
// Comma-separated list of feature names to enable. // Comma-separated list of feature names to enable.
public static final String ENABLE_FEATURES = "enable-features"; public static final String ENABLE_FEATURES = "enable-features";
......
...@@ -6,6 +6,7 @@ package org.chromium.base.library_loader; ...@@ -6,6 +6,7 @@ package org.chromium.base.library_loader;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.os.Build; import android.os.Build;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
...@@ -63,7 +64,13 @@ public class LibraryLoader { ...@@ -63,7 +64,13 @@ public class LibraryLoader {
private static final String LIBRARY_DIR = "native_libraries"; private static final String LIBRARY_DIR = "native_libraries";
// Shared preferences key for the reached code profiler. // Shared preferences key for the reached code profiler.
private static final String REACHED_CODE_PROFILER_ENABLED_KEY = "reached_code_profiler_enabled"; private static final String DEPRECATED_REACHED_CODE_PROFILER_KEY =
"reached_code_profiler_enabled";
private static final String REACHED_CODE_SAMPLING_INTERVAL_KEY =
"reached_code_sampling_interval";
// Default sampling interval for reached code profiler in microseconds.
private static final int DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US = 10000;
// The singleton instance of LibraryLoader. Never null (not final for tests). // The singleton instance of LibraryLoader. Never null (not final for tests).
private static LibraryLoader sInstance = new LibraryLoader(); private static LibraryLoader sInstance = new LibraryLoader();
...@@ -376,23 +383,35 @@ public class LibraryLoader { ...@@ -376,23 +383,35 @@ public class LibraryLoader {
* on ChromeFeatureList, and has to rely on external code pushing the value. * on ChromeFeatureList, and has to rely on external code pushing the value.
* *
* @param enabled whether to enable the reached code profiler. * @param enabled whether to enable the reached code profiler.
* @param samplingIntervalUs the sampling interval for reached code profiler.
*/ */
public static void setReachedCodeProfilerEnabledOnNextRuns(boolean enabled) { public static void setReachedCodeProfilerEnabledOnNextRuns(
ContextUtils.getAppSharedPreferences() boolean enabled, int samplingIntervalUs) {
.edit() // Store 0 if the profiler is not enabled, otherwise store the sampling interval in
.putBoolean(REACHED_CODE_PROFILER_ENABLED_KEY, enabled) // microseconds.
.apply(); if (enabled && samplingIntervalUs == 0) {
samplingIntervalUs = DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US;
} else if (!enabled) {
samplingIntervalUs = 0;
}
SharedPreferences.Editor editor = ContextUtils.getAppSharedPreferences().edit();
editor.remove(DEPRECATED_REACHED_CODE_PROFILER_KEY);
editor.putInt(REACHED_CODE_SAMPLING_INTERVAL_KEY, samplingIntervalUs).apply();
} }
/** /**
* @return whether to enable reached code profiler (see * @return sampling interval for reached code profiler, or 0 when the profiler is disabled. (see
* setReachedCodeProfilerEnabledOnNextRuns()). * setReachedCodeProfilerEnabledOnNextRuns()).
*/ */
@VisibleForTesting @VisibleForTesting
public static boolean isReachedCodeProfilerEnabled() { public static int getReachedCodeSamplingIntervalUs() {
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
return ContextUtils.getAppSharedPreferences().getBoolean( if (ContextUtils.getAppSharedPreferences().getBoolean(
REACHED_CODE_PROFILER_ENABLED_KEY, false); DEPRECATED_REACHED_CODE_PROFILER_KEY, false)) {
return DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US;
}
return ContextUtils.getAppSharedPreferences().getInt(
REACHED_CODE_SAMPLING_INTERVAL_KEY, 0);
} }
} }
...@@ -581,9 +600,14 @@ public class LibraryLoader { ...@@ -581,9 +600,14 @@ public class LibraryLoader {
// Add a switch for the reached code profiler as late as possible since it requires a read // Add a switch for the reached code profiler as late as possible since it requires a read
// from the shared preferences. At this point the shared preferences are usually warmed up. // from the shared preferences. At this point the shared preferences are usually warmed up.
if (mLibraryProcessType == LibraryProcessType.PROCESS_BROWSER if (mLibraryProcessType == LibraryProcessType.PROCESS_BROWSER) {
&& isReachedCodeProfilerEnabled()) { int reachedCodeSamplingIntervalUs = getReachedCodeSamplingIntervalUs();
CommandLine.getInstance().appendSwitch(BaseSwitches.ENABLE_REACHED_CODE_PROFILER); if (reachedCodeSamplingIntervalUs > 0) {
CommandLine.getInstance().appendSwitch(BaseSwitches.ENABLE_REACHED_CODE_PROFILER);
CommandLine.getInstance().appendSwitchWithValue(
BaseSwitches.REACHED_CODE_SAMPLING_INTERVAL_US,
Integer.toString(reachedCodeSamplingIntervalUs));
}
} }
ensureCommandLineSwitchedAlreadyLocked(); ensureCommandLineSwitchedAlreadyLocked();
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/scoped_generic.h" #include "base/scoped_generic.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
...@@ -117,7 +118,8 @@ class ReachedCodeProfiler { ...@@ -117,7 +118,8 @@ class ReachedCodeProfiler {
} }
// Starts to periodically send |kProfilerSignal| to all threads. // Starts to periodically send |kProfilerSignal| to all threads.
void Start(LibraryProcessType library_process_type) { void Start(LibraryProcessType library_process_type,
base::TimeDelta sampling_interval) {
if (is_enabled_) if (is_enabled_)
return; return;
...@@ -154,7 +156,7 @@ class ReachedCodeProfiler { ...@@ -154,7 +156,7 @@ class ReachedCodeProfiler {
// Start the interval timer. // Start the interval timer.
struct itimerspec its; struct itimerspec its;
memset(&its, 0, sizeof(its)); memset(&its, 0, sizeof(its));
its.it_interval.tv_nsec = kSamplingInterval.InNanoseconds(); its.it_interval.tv_nsec = sampling_interval.InNanoseconds();
its.it_value = its.it_interval; its.it_value = its.it_interval;
ret = timer_settime(timerid, 0, &its, nullptr); ret = timer_settime(timerid, 0, &its, nullptr);
if (ret) { if (ret) {
...@@ -268,7 +270,17 @@ void InitReachedCodeProfilerAtStartup(LibraryProcessType library_process_type) { ...@@ -268,7 +270,17 @@ void InitReachedCodeProfilerAtStartup(LibraryProcessType library_process_type) {
if (!ShouldEnableReachedCodeProfiler()) if (!ShouldEnableReachedCodeProfiler())
return; return;
ReachedCodeProfiler::GetInstance()->Start(library_process_type); int interval_us = 0;
base::TimeDelta sampling_interval = kSamplingInterval;
if (base::StringToInt(
base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
switches::kReachedCodeSamplingIntervalUs),
&interval_us) &&
interval_us > 0) {
sampling_interval = base::TimeDelta::FromMicroseconds(interval_us);
}
ReachedCodeProfiler::GetInstance()->Start(library_process_type,
sampling_interval);
} }
bool IsReachedCodeProfilerEnabled() { bool IsReachedCodeProfilerEnabled() {
......
...@@ -136,6 +136,10 @@ const char kEnableCrashReporterForTesting[] = ...@@ -136,6 +136,10 @@ const char kEnableCrashReporterForTesting[] =
// Enables the reached code profiler that samples all threads in all processes // Enables the reached code profiler that samples all threads in all processes
// to determine which functions are almost never executed. // to determine which functions are almost never executed.
const char kEnableReachedCodeProfiler[] = "enable-reached-code-profiler"; const char kEnableReachedCodeProfiler[] = "enable-reached-code-profiler";
// Specifies the profiling interval in microseconds for reached code profiler.
const char kReachedCodeSamplingIntervalUs[] =
"reached-code-sampling-interval-us";
#endif #endif
#if defined(OS_LINUX) #if defined(OS_LINUX)
......
...@@ -48,6 +48,7 @@ extern const char kEnableCrashReporterForTesting[]; ...@@ -48,6 +48,7 @@ extern const char kEnableCrashReporterForTesting[];
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
extern const char kEnableReachedCodeProfiler[]; extern const char kEnableReachedCodeProfiler[];
extern const char kReachedCodeSamplingIntervalUs[];
extern const char kOrderfileMemoryOptimization[]; extern const char kOrderfileMemoryOptimization[];
#endif #endif
......
...@@ -54,11 +54,17 @@ public final class ReachedCodeProfilerTest { ...@@ -54,11 +54,17 @@ public final class ReachedCodeProfilerTest {
*/ */
@Test @Test
@SmallTest @SmallTest
@EnableFeatures(ChromeFeatureList.REACHED_CODE_PROFILER) @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.REACHED_CODE_PROFILER + "<"
public void testEnabledViaCachedSharedPreference() { + ChromeFeatureList.REACHED_CODE_PROFILER,
LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(true); "force-fieldtrials=" + ChromeFeatureList.REACHED_CODE_PROFILER + "/" + FAKE_GROUP_NAME,
"force-fieldtrial-params=" + ChromeFeatureList.REACHED_CODE_PROFILER + "."
+ FAKE_GROUP_NAME + ":sampling_interval_us/42"})
public void
testEnabledViaCachedSharedPreference() {
LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(true, 42);
mActivityTestRule.startMainActivityFromLauncher(); mActivityTestRule.startMainActivityFromLauncher();
assertReachedCodeProfilerIsEnabled(); assertReachedCodeProfilerIsEnabled();
Assert.assertEquals(42, LibraryLoader.getReachedCodeSamplingIntervalUs());
} }
/** /**
...@@ -71,7 +77,7 @@ public final class ReachedCodeProfilerTest { ...@@ -71,7 +77,7 @@ public final class ReachedCodeProfilerTest {
public void testSharedPreferenceIsCached_Enable() { public void testSharedPreferenceIsCached_Enable() {
mActivityTestRule.startMainActivityFromLauncher(); mActivityTestRule.startMainActivityFromLauncher();
Assert.assertTrue(LibraryLoader.isReachedCodeProfilerEnabled()); Assert.assertEquals(10000, LibraryLoader.getReachedCodeSamplingIntervalUs());
// Enabling takes effect only on the second startup. // Enabling takes effect only on the second startup.
Assert.assertFalse(ReachedCodeProfiler.isEnabled()); Assert.assertFalse(ReachedCodeProfiler.isEnabled());
} }
...@@ -85,10 +91,9 @@ public final class ReachedCodeProfilerTest { ...@@ -85,10 +91,9 @@ public final class ReachedCodeProfilerTest {
@SmallTest @SmallTest
@DisableFeatures(ChromeFeatureList.REACHED_CODE_PROFILER) @DisableFeatures(ChromeFeatureList.REACHED_CODE_PROFILER)
public void testSharedPreferenceIsCached_Disable() { public void testSharedPreferenceIsCached_Disable() {
LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(true); LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(true, 0);
mActivityTestRule.startMainActivityFromLauncher(); mActivityTestRule.startMainActivityFromLauncher();
Assert.assertEquals(0, LibraryLoader.getReachedCodeSamplingIntervalUs());
Assert.assertFalse(LibraryLoader.isReachedCodeProfilerEnabled());
// Disabling takes effect only on the second startup. // Disabling takes effect only on the second startup.
assertReachedCodeProfilerIsEnabled(); assertReachedCodeProfilerIsEnabled();
} }
......
...@@ -248,7 +248,9 @@ public class CachedFeatureFlags { ...@@ -248,7 +248,9 @@ public class CachedFeatureFlags {
// Propagate REACHED_CODE_PROFILER feature value to LibraryLoader. This can't be done in // Propagate REACHED_CODE_PROFILER feature value to LibraryLoader. This can't be done in
// LibraryLoader itself because it lives in //base and can't depend on ChromeFeatureList. // LibraryLoader itself because it lives in //base and can't depend on ChromeFeatureList.
LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns( LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(
ChromeFeatureList.isEnabled(ChromeFeatureList.REACHED_CODE_PROFILER)); ChromeFeatureList.isEnabled(ChromeFeatureList.REACHED_CODE_PROFILER),
ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
ChromeFeatureList.REACHED_CODE_PROFILER, "sampling_interval_us", 0));
} }
/** /**
......
...@@ -282,6 +282,7 @@ static const char* const kSwitchNames[] = { ...@@ -282,6 +282,7 @@ static const char* const kSwitchNames[] = {
switches::kForceVideoOverlays, switches::kForceVideoOverlays,
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
switches::kEnableReachedCodeProfiler, switches::kEnableReachedCodeProfiler,
switches::kReachedCodeSamplingIntervalUs,
#endif #endif
}; };
......
...@@ -3443,6 +3443,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( ...@@ -3443,6 +3443,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
switches::kDisableMediaSessionAPI, switches::kDisableMediaSessionAPI,
switches::kEnableReachedCodeProfiler, switches::kEnableReachedCodeProfiler,
switches::kReachedCodeSamplingIntervalUs,
switches::kRendererWaitForJavaDebugger, switches::kRendererWaitForJavaDebugger,
#endif #endif
#if defined(OS_WIN) #if defined(OS_WIN)
......
...@@ -476,6 +476,7 @@ bool UtilityProcessHost::StartProcess() { ...@@ -476,6 +476,7 @@ bool UtilityProcessHost::StartProcess() {
switches::kVModule, switches::kVModule,
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
switches::kEnableReachedCodeProfiler, switches::kEnableReachedCodeProfiler,
switches::kReachedCodeSamplingIntervalUs,
#endif #endif
switches::kEnableExperimentalWebPlatformFeatures, switches::kEnableExperimentalWebPlatformFeatures,
// These flags are used by the audio service: // These flags are used by the audio service:
......
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