Skip to content

Commit

Permalink
Check the PreRead field trial options in PreReadFile.
Browse files Browse the repository at this point in the history
This ensures that the PreRead options are respected whenever
PreReadFile is called. In an upcoming CL, PreReadFile will be called
in chrome_browser_main.cc to pre-read chrome_child.dll before the first
child process is launched.

BUG=547794

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

Cr-Commit-Position: refs/heads/master@{#373823}
  • Loading branch information
fdoray authored and Commit bot committed Feb 5, 2016
1 parent 2ab00c9 commit fb9b774
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 45 deletions.
1 change: 1 addition & 0 deletions chrome/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ if (is_win) {
]
deps = [
"//base",
"//components/startup_metric_utils/common",
]
}
}
Expand Down
58 changes: 48 additions & 10 deletions chrome/app/file_pre_reader_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@

#include "base/files/file.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_restrictions.h"
#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"

void PreReadFile(const base::FilePath& file_path) {
base::ThreadRestrictions::AssertIOAllowed();
namespace {

// Pre-reads |file_path| using ::ReadFile.
void PreReadFileUsingReadFile(const base::FilePath& file_path) {
base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
base::File::FLAG_SEQUENTIAL_SCAN);
if (!file.IsValid())
Expand All @@ -29,21 +33,29 @@ void PreReadFile(const base::FilePath& file_path) {
::VirtualFree(buffer, 0, MEM_RELEASE);
}

void PreReadMemoryMappedFile(const base::MemoryMappedFile& memory_mapped_file,
const base::FilePath& file_path) {
base::ThreadRestrictions::AssertIOAllowed();
if (!memory_mapped_file.IsValid())
return;

// Pre-reads |file_path| using ::PrefetchVirtualMemory, if available. Otherwise,
// falls back on using ::ReadFile.
void PreReadFileUsingPrefetchVirtualMemory(const base::FilePath& file_path) {
// Load ::PrefetchVirtualMemory dynamically, because it is only available on
// Win8+.
using PrefetchVirtualMemoryPtr = decltype(::PrefetchVirtualMemory)*;
PrefetchVirtualMemoryPtr prefetch_virtual_memory =
reinterpret_cast<PrefetchVirtualMemoryPtr>(::GetProcAddress(
::GetModuleHandle(L"kernel32.dll"), "PrefetchVirtualMemory"));
if (!prefetch_virtual_memory) {
// If ::PrefetchVirtualMemory is not available, fall back to PreReadFile.
PreReadFile(file_path);
// If ::PrefetchVirtualMemory is not available, fall back to
// PreReadFileUsingReadFile().
PreReadFileUsingReadFile(file_path);
return;
}

base::MemoryMappedFile memory_mapped_file;
if (!memory_mapped_file.Initialize(file_path)) {
// Initializing the memory map should not fail. If it does fail in a debug
// build, we want to be warned about it so that we can investigate the
// failure.
NOTREACHED();
PreReadFileUsingReadFile(file_path);
return;
}

Expand All @@ -53,3 +65,29 @@ void PreReadMemoryMappedFile(const base::MemoryMappedFile& memory_mapped_file,
memory_range.NumberOfBytes = memory_mapped_file.length();
prefetch_virtual_memory(::GetCurrentProcess(), 1U, &memory_range, 0);
}

} // namespace

void PreReadFile(const base::FilePath& file_path,
const startup_metric_utils::PreReadOptions& pre_read_options) {
DCHECK(pre_read_options.pre_read);
base::ThreadRestrictions::AssertIOAllowed();

// Increase thread priority if necessary.
base::ThreadPriority previous_priority = base::ThreadPriority::NORMAL;
if (pre_read_options.high_priority) {
previous_priority = base::PlatformThread::GetCurrentThreadPriority();
base::PlatformThread::SetCurrentThreadPriority(
base::ThreadPriority::DISPLAY);
}

// Pre-read |file_path|.
if (pre_read_options.prefetch_virtual_memory)
PreReadFileUsingPrefetchVirtualMemory(file_path);
else
PreReadFileUsingReadFile(file_path);

// Reset thread priority.
if (pre_read_options.high_priority)
base::PlatformThread::SetCurrentThreadPriority(previous_priority);
}
17 changes: 7 additions & 10 deletions chrome/app/file_pre_reader_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@

namespace base {
class FilePath;
class MemoryMappedFile;
}

// Reads |file_path| to avoid touching the disk when the file is actually used.
void PreReadFile(const base::FilePath& file_path);
namespace startup_metric_utils {
struct PreReadOptions;
}

// Reads |memory_mapped_file| to avoid touching the disk when the mapped file is
// actually used. The function checks the Windows version to determine which
// pre-reading mechanism to use. On Win8+, it uses ::PrefetchVirtualMemory. On
// previous Windows versions, is uses PreReadFile (declared above). |file_path|
// is the path to the memory mapped file.
void PreReadMemoryMappedFile(const base::MemoryMappedFile& memory_mapped_file,
const base::FilePath& file_path);
// Pre-reads |file_path| to avoid touching the disk when the file is actually
// used. Checks |pre_read_options| to determine how to pre-read the file.
void PreReadFile(const base::FilePath& file_path,
const startup_metric_utils::PreReadOptions& pre_read_options);

#endif // CHROME_APP_FILE_PRE_READER_WIN_H_
28 changes: 3 additions & 25 deletions chrome/app/main_dll_loader_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/environment.h"
#include "base/files/memory_mapped_file.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
Expand All @@ -24,7 +23,6 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
#include "base/trace_event/trace_event.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
Expand Down Expand Up @@ -62,31 +60,11 @@ typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)();
HMODULE LoadModuleWithDirectory(const base::FilePath& module) {
::SetCurrentDirectoryW(module.DirName().value().c_str());

// Get pre-read options from the PreRead field trial.
// Pre-read the binary to warm the memory caches (avoids a lot of random IO).
const startup_metric_utils::PreReadOptions pre_read_options =
startup_metric_utils::GetPreReadOptions();

// Pre-read the binary to warm the memory caches (avoids a lot of random IO).
if (pre_read_options.pre_read) {
base::ThreadPriority previous_priority = base::ThreadPriority::NORMAL;
if (pre_read_options.high_priority) {
previous_priority = base::PlatformThread::GetCurrentThreadPriority();
base::PlatformThread::SetCurrentThreadPriority(
base::ThreadPriority::DISPLAY);
}

if (pre_read_options.prefetch_virtual_memory) {
base::MemoryMappedFile module_memory_map;
const bool map_initialize_success = module_memory_map.Initialize(module);
DCHECK(map_initialize_success);
PreReadMemoryMappedFile(module_memory_map, module);
} else {
PreReadFile(module);
}

if (pre_read_options.high_priority)
base::PlatformThread::SetCurrentThreadPriority(previous_priority);
}
if (pre_read_options.pre_read)
PreReadFile(module, pre_read_options);

return ::LoadLibraryExW(module.value().c_str(), nullptr,
LOAD_WITH_ALTERED_SEARCH_PATH);
Expand Down
1 change: 1 addition & 0 deletions chrome/chrome_exe.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@
],
'dependencies': [
'../base/base.gyp:base',
'../components/components.gyp:startup_metric_utils_common',
],
},
],
Expand Down

0 comments on commit fb9b774

Please sign in to comment.