| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/app/file_pre_reader_win.h" | 5 #include "chrome/app/file_pre_reader_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/files/file.h" | 9 #include "base/files/file.h" |
| 10 #include "base/files/memory_mapped_file.h" | |
| 11 #include "base/logging.h" | |
| 12 #include "base/threading/platform_thread.h" | |
| 13 #include "base/threading/thread_restrictions.h" | |
| 14 #include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.
h" | |
| 15 | 10 |
| 16 namespace { | 11 void PreReadFile(const base::FilePath& file_path) { |
| 17 | |
| 18 // Pre-reads |file_path| using ::ReadFile. | |
| 19 void PreReadFileUsingReadFile(const base::FilePath& file_path) { | |
| 20 base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ | | 12 base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ | |
| 21 base::File::FLAG_SEQUENTIAL_SCAN); | 13 base::File::FLAG_SEQUENTIAL_SCAN); |
| 22 if (!file.IsValid()) | 14 if (!file.IsValid()) |
| 23 return; | 15 return; |
| 24 | 16 |
| 17 // This could be replaced with ::PrefetchVirtualMemory once we drop support |
| 18 // for Win7. The performance of ::PrefetchVirtualMemory is roughly equivalent |
| 19 // to these buffered reads. |
| 25 const DWORD kStepSize = 1024 * 1024; | 20 const DWORD kStepSize = 1024 * 1024; |
| 26 char* buffer = reinterpret_cast<char*>( | 21 char* buffer = reinterpret_cast<char*>( |
| 27 ::VirtualAlloc(nullptr, kStepSize, MEM_COMMIT, PAGE_READWRITE)); | 22 ::VirtualAlloc(nullptr, kStepSize, MEM_COMMIT, PAGE_READWRITE)); |
| 28 if (!buffer) | 23 if (!buffer) |
| 29 return; | 24 return; |
| 30 | 25 |
| 31 while (file.ReadAtCurrentPos(buffer, kStepSize) > 0) {} | 26 while (file.ReadAtCurrentPos(buffer, kStepSize) > 0) {} |
| 32 | 27 |
| 33 ::VirtualFree(buffer, 0, MEM_RELEASE); | 28 ::VirtualFree(buffer, 0, MEM_RELEASE); |
| 34 } | 29 } |
| 35 | |
| 36 // Pre-reads |file_path| using ::PrefetchVirtualMemory, if available. Otherwise, | |
| 37 // falls back on using ::ReadFile. | |
| 38 void PreReadFileUsingPrefetchVirtualMemory(const base::FilePath& file_path) { | |
| 39 // Load ::PrefetchVirtualMemory dynamically, because it is only available on | |
| 40 // Win8+. | |
| 41 using PrefetchVirtualMemoryPtr = decltype(::PrefetchVirtualMemory)*; | |
| 42 PrefetchVirtualMemoryPtr prefetch_virtual_memory = | |
| 43 reinterpret_cast<PrefetchVirtualMemoryPtr>(::GetProcAddress( | |
| 44 ::GetModuleHandle(L"kernel32.dll"), "PrefetchVirtualMemory")); | |
| 45 if (!prefetch_virtual_memory) { | |
| 46 // If ::PrefetchVirtualMemory is not available, fall back to | |
| 47 // PreReadFileUsingReadFile(). | |
| 48 PreReadFileUsingReadFile(file_path); | |
| 49 return; | |
| 50 } | |
| 51 | |
| 52 base::MemoryMappedFile memory_mapped_file; | |
| 53 if (!memory_mapped_file.Initialize(file_path)) { | |
| 54 // Initializing the memory map should not fail. If it does fail in a debug | |
| 55 // build, we want to be warned about it so that we can investigate the | |
| 56 // failure. | |
| 57 NOTREACHED(); | |
| 58 PreReadFileUsingReadFile(file_path); | |
| 59 return; | |
| 60 } | |
| 61 | |
| 62 WIN32_MEMORY_RANGE_ENTRY memory_range; | |
| 63 memory_range.VirtualAddress = const_cast<void*>( | |
| 64 reinterpret_cast<const void*>(memory_mapped_file.data())); | |
| 65 memory_range.NumberOfBytes = memory_mapped_file.length(); | |
| 66 prefetch_virtual_memory(::GetCurrentProcess(), 1U, &memory_range, 0); | |
| 67 } | |
| 68 | |
| 69 } // namespace | |
| 70 | |
| 71 void PreReadFile(const base::FilePath& file_path, | |
| 72 const startup_metric_utils::PreReadOptions& pre_read_options) { | |
| 73 DCHECK(pre_read_options.pre_read); | |
| 74 base::ThreadRestrictions::AssertIOAllowed(); | |
| 75 | |
| 76 // Increase thread priority if necessary. | |
| 77 base::ThreadPriority previous_priority = base::ThreadPriority::NORMAL; | |
| 78 if (pre_read_options.high_priority) { | |
| 79 previous_priority = base::PlatformThread::GetCurrentThreadPriority(); | |
| 80 base::PlatformThread::SetCurrentThreadPriority( | |
| 81 base::ThreadPriority::DISPLAY); | |
| 82 } | |
| 83 | |
| 84 // Pre-read |file_path|. | |
| 85 if (pre_read_options.prefetch_virtual_memory) | |
| 86 PreReadFileUsingPrefetchVirtualMemory(file_path); | |
| 87 else | |
| 88 PreReadFileUsingReadFile(file_path); | |
| 89 | |
| 90 // Reset thread priority. | |
| 91 if (pre_read_options.high_priority) | |
| 92 base::PlatformThread::SetCurrentThreadPriority(previous_priority); | |
| 93 } | |
| OLD | NEW |