Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Side by Side Diff: chrome/app/image_pre_reader_win.cc

Issue 23534009: Re-enable pre-read experiment as a finch field trial. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix comment and rebase Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/image_pre_reader_win.h" 5 #include "chrome/app/image_pre_reader_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <limits> 9 #include <limits>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/threading/thread_restrictions.h" 14 #include "base/threading/thread_restrictions.h"
15 #include "base/win/pe_image.h" 15 #include "base/win/pe_image.h"
16 #include "base/win/scoped_handle.h" 16 #include "base/win/scoped_handle.h"
17 #include "base/win/windows_version.h" 17 #include "base/win/windows_version.h"
18 18
19 namespace { 19 namespace {
20 20
21 // The minimum buffer size to allocate when reading the PE file headers. 21 // The minimum buffer size to allocate when reading the PE file headers.
22 // 22 //
23 // The PE file headers usually fit into a single 1KB page, and a PE file must 23 // The PE file headers usually fit into a single 1KB page, and a PE file must
24 // at least contain the initial page with the headers. That said, as long as 24 // at least contain the initial page with the headers. That said, as long as
25 // we expect at least sizeof(IMAGE_DOS_HEADER) bytes, we're ok. 25 // we expect at least sizeof(IMAGE_DOS_HEADER) bytes, we're ok.
26 const size_t kMinHeaderBufferSize = 0x400; 26 const size_t kMinHeaderBufferSize = 0x400;
27 27
28 // A handy symbolic constant. 28 // A handy symbolic constant.
29 const uint8 kOneHundredPercent = 100; 29 const size_t kOneHundredPercent = 100;
30 30
31 void StaticAssertions() { 31 void StaticAssertions() {
32 COMPILE_ASSERT(kMinHeaderBufferSize >= sizeof(IMAGE_DOS_HEADER), 32 COMPILE_ASSERT(kMinHeaderBufferSize >= sizeof(IMAGE_DOS_HEADER),
33 min_header_buffer_size_at_least_as_big_as_the_dos_header); 33 min_header_buffer_size_at_least_as_big_as_the_dos_header);
34 } 34 }
35 35
36 // This struct provides a deallocation functor for use with scoped_ptr<T> 36 // This struct provides a deallocation functor for use with scoped_ptr<T>
37 // allocated with ::VirtualAlloc(). 37 // allocated with ::VirtualAlloc().
38 struct ScopedPtrVirtualFree { 38 struct ScopedPtrVirtualFree {
39 void operator() (void* ptr) { 39 void operator() (void* ptr) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 // 98 //
99 // Note that sections can have their tails implicitly initialized to zero 99 // Note that sections can have their tails implicitly initialized to zero
100 // (i.e., their virtual size is larger than the raw size) and that raw data 100 // (i.e., their virtual size is larger than the raw size) and that raw data
101 // is padded to the PE page size if the entire section is initialized (i.e., 101 // is padded to the PE page size if the entire section is initialized (i.e.,
102 // their raw data size will be larger than the virtual size). 102 // their raw data size will be larger than the virtual size).
103 // 103 //
104 // Any data after the initialized portion of the section will be soft-faulted 104 // Any data after the initialized portion of the section will be soft-faulted
105 // in (very quickly) as needed, so we don't need to include it in the returned 105 // in (very quickly) as needed, so we don't need to include it in the returned
106 // length. 106 // length.
107 size_t GetPercentageOfSectionLength(const IMAGE_SECTION_HEADER* section, 107 size_t GetPercentageOfSectionLength(const IMAGE_SECTION_HEADER* section,
108 uint8 percentage) { 108 size_t percentage) {
109 DCHECK(section != NULL); 109 DCHECK(section != NULL);
110 DCHECK_GT(percentage, 0); 110 DCHECK_GT(percentage, 0u);
111 DCHECK_LE(percentage, kOneHundredPercent); 111 DCHECK_LE(percentage, kOneHundredPercent);
112 112
113 size_t initialized_length = std::min(section->SizeOfRawData, 113 size_t initialized_length = std::min(section->SizeOfRawData,
114 section->Misc.VirtualSize); 114 section->Misc.VirtualSize);
115 115
116 if (initialized_length == 0) 116 if (initialized_length == 0)
117 return 0; 117 return 0;
118 118
119 size_t length = (initialized_length * percentage) / kOneHundredPercent; 119 size_t length = (initialized_length * percentage) / kOneHundredPercent;
120 120
121 return std::max<size_t>(length, 1); 121 return std::max<size_t>(length, 1);
122 } 122 }
123 123
124 // Helper function to read through a |percentage| of the given |section| 124 // Helper function to read through a |percentage| of the given |section|
125 // of the file denoted by |file_handle|. The |temp_buffer| is (re)used as 125 // of the file denoted by |file_handle|. The |temp_buffer| is (re)used as
126 // a transient storage area as the section is read in chunks of 126 // a transient storage area as the section is read in chunks of
127 // |temp_buffer_size| bytes. 127 // |temp_buffer_size| bytes.
128 bool ReadThroughSection(HANDLE file_handle, 128 bool ReadThroughSection(HANDLE file_handle,
129 const IMAGE_SECTION_HEADER* section, 129 const IMAGE_SECTION_HEADER* section,
130 uint8 percentage, 130 size_t percentage,
131 void* temp_buffer, 131 void* temp_buffer,
132 size_t temp_buffer_size) { 132 size_t temp_buffer_size) {
133 DCHECK(file_handle != INVALID_HANDLE_VALUE); 133 DCHECK(file_handle != INVALID_HANDLE_VALUE);
134 DCHECK(section != NULL); 134 DCHECK(section != NULL);
135 DCHECK_LE(percentage, kOneHundredPercent); 135 DCHECK_LE(percentage, kOneHundredPercent);
136 DCHECK(temp_buffer != NULL); 136 DCHECK(temp_buffer != NULL);
137 DCHECK(temp_buffer_size > 0); 137 DCHECK(temp_buffer_size > 0);
138 138
139 size_t bytes_to_read = GetPercentageOfSectionLength(section, percentage); 139 size_t bytes_to_read = GetPercentageOfSectionLength(section, percentage);
140 if (bytes_to_read == 0) 140 if (bytes_to_read == 0)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 while (touch_ptr < final_touch_ptr) { 182 while (touch_ptr < final_touch_ptr) {
183 dummy = *touch_ptr; 183 dummy = *touch_ptr;
184 touch_ptr += system_info.dwPageSize; 184 touch_ptr += system_info.dwPageSize;
185 } 185 }
186 dummy = *final_touch_ptr; 186 dummy = *final_touch_ptr;
187 } 187 }
188 188
189 } // namespace 189 } // namespace
190 190
191 bool ImagePreReader::PartialPreReadImageOnDisk(const wchar_t* file_path, 191 bool ImagePreReader::PartialPreReadImageOnDisk(const wchar_t* file_path,
192 uint8 percentage, 192 size_t percentage,
193 size_t max_chunk_size) { 193 size_t max_chunk_size) {
194 // TODO(rogerm): change this to have the number of bytes pre-read per 194 // TODO(rogerm): change this to have the number of bytes pre-read per
195 // section be driven by a static table within the PE file (defaulting to 195 // section be driven by a static table within the PE file (defaulting to
196 // full read if it's not there?) that's initialized by the optimization 196 // full read if it's not there?) that's initialized by the optimization
197 // toolchain. 197 // toolchain.
198 DCHECK(file_path != NULL); 198 DCHECK(file_path != NULL);
199 199
200 if (percentage == 0) 200 if (percentage == 0)
201 return true; 201 return true;
202 202
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 if (!ReadThroughSection( 266 if (!ReadThroughSection(
267 file, section, percentage, buffer.get(), max_chunk_size)) 267 file, section, percentage, buffer.get(), max_chunk_size))
268 return false; 268 return false;
269 } 269 }
270 270
271 // We're done. 271 // We're done.
272 return true; 272 return true;
273 } 273 }
274 274
275 bool ImagePreReader::PartialPreReadImageInMemory(const wchar_t* file_path, 275 bool ImagePreReader::PartialPreReadImageInMemory(const wchar_t* file_path,
276 uint8 percentage) { 276 size_t percentage) {
277 // TODO(rogerm): change this to have the number of bytes pre-read per 277 // TODO(rogerm): change this to have the number of bytes pre-read per
278 // section be driven by a static table within the PE file (defaulting to 278 // section be driven by a static table within the PE file (defaulting to
279 // full read if it's not there?) that's initialized by the optimization 279 // full read if it's not there?) that's initialized by the optimization
280 // toolchain. 280 // toolchain.
281 DCHECK(file_path != NULL); 281 DCHECK(file_path != NULL);
282 282
283 if (percentage == 0) 283 if (percentage == 0)
284 return true; 284 return true;
285 285
286 if (percentage > kOneHundredPercent) 286 if (percentage > kOneHundredPercent)
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 389
390 // Page in then release the module. 390 // Page in then release the module.
391 TouchPagesInRange(dll_module, dll_module_length); 391 TouchPagesInRange(dll_module, dll_module_length);
392 FreeLibrary(dll_module); 392 FreeLibrary(dll_module);
393 } 393 }
394 394
395 return true; 395 return true;
396 } 396 }
397 397
398 bool ImagePreReader::PartialPreReadImage(const wchar_t* file_path, 398 bool ImagePreReader::PartialPreReadImage(const wchar_t* file_path,
399 uint8 percentage, 399 size_t percentage,
400 size_t max_chunk_size) { 400 size_t max_chunk_size) {
401 base::ThreadRestrictions::AssertIOAllowed(); 401 base::ThreadRestrictions::AssertIOAllowed();
402 402
403 if (percentage >= kOneHundredPercent) { 403 if (percentage >= kOneHundredPercent) {
404 // If we're reading the whole image, we don't need to parse headers and 404 // If we're reading the whole image, we don't need to parse headers and
405 // navigate sections, the basic PreReadImage() can be used to just step 405 // navigate sections, the basic PreReadImage() can be used to just step
406 // blindly through the entire file / address-space. 406 // blindly through the entire file / address-space.
407 return PreReadImage(file_path, 0, max_chunk_size); 407 return PreReadImage(file_path, 0, max_chunk_size);
408 } 408 }
409 409
410 if (base::win::GetVersion() > base::win::VERSION_XP) { 410 if (base::win::GetVersion() > base::win::VERSION_XP) {
411 // Vista+ branch. On these OSes, we warm up the Image by reading its 411 // Vista+ branch. On these OSes, we warm up the Image by reading its
412 // file off the disk. 412 // file off the disk.
413 return PartialPreReadImageOnDisk(file_path, percentage, max_chunk_size); 413 return PartialPreReadImageOnDisk(file_path, percentage, max_chunk_size);
414 } 414 }
415 415
416 // WinXP branch. For XP, reading the image from disk doesn't do what we want 416 // WinXP branch. For XP, reading the image from disk doesn't do what we want
417 // so instead we pull the pages into memory by loading the DLL and touching 417 // so instead we pull the pages into memory by loading the DLL and touching
418 // initialized pages at a stride. 418 // initialized pages at a stride.
419 return PartialPreReadImageInMemory(file_path, percentage); 419 return PartialPreReadImageInMemory(file_path, percentage);
420 } 420 }
OLDNEW
« no previous file with comments | « chrome/app/image_pre_reader_win.h ('k') | chrome/browser/chrome_browser_field_trials_desktop.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698