Commit dee06429 authored by fdoray's avatar fdoray Committed by Commit bot

Store PreRead options obtained from the registry in a global variable.

Instead of reading PreRead options from the registry every time they
are needed, read them once and store them in a global variable.
This optimization isn't immediately useful as PreRead options are
currently read only once per process. However, with the upcoming
/prefetch:# experiment, the browser process will need the PreRead
options every time it launches a process.

This CL also has these benefits:
- The caller of GetPreReadOptions doesn't need to know the product
  registry path. This will allow content to get the PreRead options
  to decide whether it should use a /prefetch:# switch when
  launching a process.
- The PreRead options are returned as a bit field instead of by
  setting multiple booleans. This will facilitate the addition of
  new PreRead options.

BUG=577698

Review URL: https://codereview.chromium.org/1610733002

Cr-Commit-Position: refs/heads/master@{#370805}
parent cdb380ab
...@@ -64,35 +64,31 @@ HMODULE LoadModuleWithDirectory(const base::FilePath& module) { ...@@ -64,35 +64,31 @@ HMODULE LoadModuleWithDirectory(const base::FilePath& module) {
::SetCurrentDirectoryW(module.DirName().value().c_str()); ::SetCurrentDirectoryW(module.DirName().value().c_str());
// Get pre-read options from the PreRead field trial. // Get pre-read options from the PreRead field trial.
bool trial_no_pre_read = false; startup_metric_utils::InitializePreReadOptions(
bool trial_high_priority = false; BrowserDistribution::GetDistribution()->GetRegistryPath());
bool trial_only_if_cold = false; const startup_metric_utils::PreReadOptions pre_read_options =
bool trial_prefetch_virtual_memory = false; startup_metric_utils::GetPreReadOptions();
startup_metric_utils::GetPreReadOptions(
BrowserDistribution::GetDistribution()->GetRegistryPath(),
&trial_no_pre_read, &trial_high_priority, &trial_only_if_cold,
&trial_prefetch_virtual_memory);
// Pre-read the binary to warm the memory caches (avoids a lot of random IO). // Pre-read the binary to warm the memory caches (avoids a lot of random IO).
if (!trial_no_pre_read) { if (!pre_read_options.no_pre_read) {
base::ThreadPriority previous_priority = base::ThreadPriority::NORMAL; base::ThreadPriority previous_priority = base::ThreadPriority::NORMAL;
if (trial_high_priority) { if (pre_read_options.high_priority) {
previous_priority = base::PlatformThread::GetCurrentThreadPriority(); previous_priority = base::PlatformThread::GetCurrentThreadPriority();
base::PlatformThread::SetCurrentThreadPriority( base::PlatformThread::SetCurrentThreadPriority(
base::ThreadPriority::DISPLAY); base::ThreadPriority::DISPLAY);
} }
if (trial_only_if_cold) { if (pre_read_options.only_if_cold) {
base::MemoryMappedFile module_memory_map; base::MemoryMappedFile module_memory_map;
const bool map_initialize_success = module_memory_map.Initialize(module); const bool map_initialize_success = module_memory_map.Initialize(module);
DCHECK(map_initialize_success); DCHECK(map_initialize_success);
if (!IsMemoryMappedFileWarm(module_memory_map)) { if (!IsMemoryMappedFileWarm(module_memory_map)) {
if (trial_prefetch_virtual_memory) if (pre_read_options.prefetch_virtual_memory)
PreReadMemoryMappedFile(module_memory_map, module); PreReadMemoryMappedFile(module_memory_map, module);
else else
PreReadFile(module); PreReadFile(module);
} }
} else if (trial_prefetch_virtual_memory) { } else if (pre_read_options.prefetch_virtual_memory) {
base::MemoryMappedFile module_memory_map; base::MemoryMappedFile module_memory_map;
const bool map_initialize_success = module_memory_map.Initialize(module); const bool map_initialize_success = module_memory_map.Initialize(module);
DCHECK(map_initialize_success); DCHECK(map_initialize_success);
...@@ -101,7 +97,7 @@ HMODULE LoadModuleWithDirectory(const base::FilePath& module) { ...@@ -101,7 +97,7 @@ HMODULE LoadModuleWithDirectory(const base::FilePath& module) {
PreReadFile(module); PreReadFile(module);
} }
if (trial_high_priority) if (pre_read_options.high_priority)
base::PlatformThread::SetCurrentThreadPriority(previous_priority); base::PlatformThread::SetCurrentThreadPriority(previous_priority);
} }
......
...@@ -35,6 +35,10 @@ const base::char16 kPrefetchVirtualMemoryVariationName[] = ...@@ -35,6 +35,10 @@ const base::char16 kPrefetchVirtualMemoryVariationName[] =
// Registry key in which the PreRead field trial group is stored. // Registry key in which the PreRead field trial group is stored.
const base::char16 kPreReadFieldTrialRegistryKey[] = L"\\PreReadFieldTrial"; const base::char16 kPreReadFieldTrialRegistryKey[] = L"\\PreReadFieldTrial";
// Pre-read options to use for the current process. This is initialized by
// InitializePreReadOptions().
PreReadOptions g_pre_read_options = {false, false, false, false};
// Returns the registry path in which the PreRead group is stored. // Returns the registry path in which the PreRead group is stored.
base::string16 GetPreReadRegistryPath( base::string16 GetPreReadRegistryPath(
const base::string16& product_registry_path) { const base::string16& product_registry_path) {
...@@ -43,16 +47,8 @@ base::string16 GetPreReadRegistryPath( ...@@ -43,16 +47,8 @@ base::string16 GetPreReadRegistryPath(
} // namespace } // namespace
void GetPreReadOptions(const base::string16& product_registry_path, void InitializePreReadOptions(const base::string16& product_registry_path) {
bool* no_pre_read,
bool* high_priority,
bool* only_if_cold,
bool* prefetch_virtual_memory) {
DCHECK(!product_registry_path.empty()); DCHECK(!product_registry_path.empty());
DCHECK(no_pre_read);
DCHECK(high_priority);
DCHECK(only_if_cold);
DCHECK(prefetch_virtual_memory);
// Open the PreRead field trial's registry key. // Open the PreRead field trial's registry key.
const base::string16 registry_path = const base::string16 registry_path =
...@@ -61,25 +57,33 @@ void GetPreReadOptions(const base::string16& product_registry_path, ...@@ -61,25 +57,33 @@ void GetPreReadOptions(const base::string16& product_registry_path,
KEY_QUERY_VALUE); KEY_QUERY_VALUE);
// Set the PreRead field trial's options. // Set the PreRead field trial's options.
struct VariationMapping { struct {
const base::char16* name; const base::char16* name;
bool* variable; bool* option;
} const variations_mappings[] = { } const variations_mappings[] = {
{kNoPreReadVariationName, no_pre_read}, {kNoPreReadVariationName, &g_pre_read_options.no_pre_read},
{kHighPriorityVariationName, high_priority}, {kHighPriorityVariationName, &g_pre_read_options.high_priority},
{kOnlyIfColdVariationName, only_if_cold}, {kOnlyIfColdVariationName, &g_pre_read_options.only_if_cold},
{kPrefetchVirtualMemoryVariationName, prefetch_virtual_memory}, {kPrefetchVirtualMemoryVariationName,
&g_pre_read_options.prefetch_virtual_memory},
}; };
for (const auto& mapping : variations_mappings) { for (const auto& mapping : variations_mappings) {
// Set the option variable to true if the corresponding value is found in // Set the option variable to true if the corresponding value is found in
// the registry. Set to false otherwise (default behavior). // the registry. Set to false otherwise (default behavior).
DWORD value = 0; DWORD value = 0;
*mapping.variable = key.ReadValueDW(mapping.name, &value) == ERROR_SUCCESS; if (key.ReadValueDW(mapping.name, &value) == ERROR_SUCCESS) {
DCHECK(!*mapping.variable || value == 1); DCHECK_EQ(1U, value);
DCHECK(!*mapping.option);
*mapping.option = true;
}
} }
} }
PreReadOptions GetPreReadOptions() {
return g_pre_read_options;
}
void UpdatePreReadOptions(const base::string16& product_registry_path) { void UpdatePreReadOptions(const base::string16& product_registry_path) {
DCHECK(!product_registry_path.empty()); DCHECK(!product_registry_path.empty());
......
...@@ -19,19 +19,29 @@ namespace startup_metric_utils { ...@@ -19,19 +19,29 @@ namespace startup_metric_utils {
using RegisterPreReadSyntheticFieldTrialCallback = using RegisterPreReadSyntheticFieldTrialCallback =
const base::Callback<bool(const std::string&, const std::string&)>; const base::Callback<bool(const std::string&, const std::string&)>;
// Get DLL pre-reading options. |product_registry_path| is the registry path // The options controlled by the PreRead field trial.
// under which the registry key for this field trial resides. The |no_pre_read| struct PreReadOptions {
// option is set if DLLs should not be pre-read. The |high_priority| option is // No explicit DLL pre-reading.
// set if pre-reading should be done with a high thread priority. The bool no_pre_read;
// |only_if_cold| option is set if only cold DLLs should be pre-read. The
// |prefetch_virtual_memory| option is set if the // Pre-read DLLs with a high thread priority.
// ::PrefetchVirtualMemory function should be used to pre-read DLLs, if bool high_priority;
// available.
void GetPreReadOptions(const base::string16& product_registry_path, // Pre-read DLLs only when they are cold.
bool* no_pre_read, bool only_if_cold;
bool* high_priority,
bool* only_if_cold, // Pre-read DLLs using the ::PrefetchVirtualMemory function, if available.
bool* prefetch_virtual_memory); bool prefetch_virtual_memory;
};
// Initializes DLL pre-reading options from the registry.
// |product_registry_path| is the registry path under which the registry key for
// this field trial resides.
void InitializePreReadOptions(const base::string16& product_registry_path);
// Returns the bitfield of the DLL pre-reading options to use for the current
// process. InitializePreReadOptions() must have been called before this.
PreReadOptions GetPreReadOptions();
// Updates DLL pre-reading options in the registry with the latest info for the // Updates DLL pre-reading options in the registry with the latest info for the
// next startup. |product_registry_path| is the registry path under which the // next startup. |product_registry_path| is the registry path under which the
......
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