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 <windows.h> | 5 #include <windows.h> |
6 #include <shlwapi.h> | 6 #include <shlwapi.h> |
7 | 7 |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/environment.h" | 10 #include "base/environment.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
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/rand_util.h" // For PreRead experiment. | 14 #include "base/rand_util.h" // For PreRead experiment. |
15 #include "base/sha1.h" // For PreRead experiment. | 15 #include "base/sha1.h" // For PreRead experiment. |
16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
17 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
18 #include "base/version.h" | 18 #include "base/version.h" |
19 #include "base/win/registry.h" | 19 #include "base/win/registry.h" |
20 #include "chrome/app/breakpad_win.h" | 20 #include "chrome/app/breakpad_win.h" |
21 #include "chrome/app/client_util.h" | 21 #include "chrome/app/client_util.h" |
22 #include "chrome/app/image_pre_reader_win.h" | |
22 #include "chrome/common/chrome_constants.h" | 23 #include "chrome/common/chrome_constants.h" |
23 #include "chrome/common/chrome_result_codes.h" | 24 #include "chrome/common/chrome_result_codes.h" |
24 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
25 #include "chrome/installer/util/browser_distribution.h" | 26 #include "chrome/installer/util/browser_distribution.h" |
26 #include "chrome/installer/util/channel_info.h" | 27 #include "chrome/installer/util/channel_info.h" |
27 #include "chrome/installer/util/install_util.h" | 28 #include "chrome/installer/util/install_util.h" |
28 #include "chrome/installer/util/google_update_constants.h" | 29 #include "chrome/installer/util/google_update_constants.h" |
29 #include "chrome/installer/util/google_update_settings.h" | 30 #include "chrome/installer/util/google_update_settings.h" |
30 #include "chrome/installer/util/util_constants.h" | 31 #include "chrome/installer/util/util_constants.h" |
31 | 32 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 // but by default it is enabled in release builds. The ability to disable it | 177 // but by default it is enabled in release builds. The ability to disable it |
177 // is useful for evaluating competing optimization techniques. | 178 // is useful for evaluating competing optimization techniques. |
178 if (!cmd_line.HasSwitch(switches::kProcessType)) { | 179 if (!cmd_line.HasSwitch(switches::kProcessType)) { |
179 // The kernel brings in 8 pages for the code section at a time and 4 pages | 180 // The kernel brings in 8 pages for the code section at a time and 4 pages |
180 // for other sections. We can skip over these pages to avoid a soft page | 181 // for other sections. We can skip over these pages to avoid a soft page |
181 // fault which may not occur during code execution. However skipping 4K at | 182 // fault which may not occur during code execution. However skipping 4K at |
182 // a time still has better performance over 32K and 16K according to data. | 183 // a time still has better performance over 32K and 16K according to data. |
183 // TODO(ananta): Investigate this and tune. | 184 // TODO(ananta): Investigate this and tune. |
184 const size_t kStepSize = 4 * 1024; | 185 const size_t kStepSize = 4 * 1024; |
185 | 186 |
187 // We hypothesize that pre-reading only the bytes actually touched during | |
188 // startup should improve startup time. The Syzygy toolchain attempts to | |
189 // optimize the binary layout of chrome.dll, rearranging the code and data | |
190 // blocks such that temporally related blocks (i.e., code and data used in | |
191 // startup, browser, renderer, etc) are grouped together, and that blocks | |
192 // used early in the process lifecycle occur earlier in their sections. | |
193 // Our most recent results in the lab show that around 20% of code and 30% | |
194 // of data is touched during startup. The value below is an experiment | |
195 // to see what happens to startup time when we read just a percentage | |
196 // of each section of the binary versus reading the entire thing. | |
197 // TODO(rogerm): Investigate/validate this and (if benefical) automate | |
198 // the process of determining how much to read from each section | |
199 // and embed that info somewhere. | |
200 const DWORD kPreReadPercentage = 25; | |
201 | |
186 DWORD pre_read_size = 0; | 202 DWORD pre_read_size = 0; |
203 DWORD pre_read_percentage = kPreReadPercentage; | |
187 DWORD pre_read_step_size = kStepSize; | 204 DWORD pre_read_step_size = kStepSize; |
188 DWORD pre_read = 1; | 205 DWORD pre_read = 1; |
206 bool use_registry = false; | |
189 | 207 |
190 // TODO(chrisha): This path should not be ChromeFrame specific, and it | 208 // TODO(chrisha): This path should not be ChromeFrame specific, and it |
191 // should not be hard-coded with 'Google' in the path. Rather, it should | 209 // should not be hard-coded with 'Google' in the path. Rather, it should |
192 // use the product name. | 210 // use the product name. |
193 base::win::RegKey key(HKEY_CURRENT_USER, L"Software\\Google\\ChromeFrame", | 211 base::win::RegKey key(HKEY_CURRENT_USER, L"Software\\Google\\ChromeFrame", |
194 KEY_QUERY_VALUE); | 212 KEY_QUERY_VALUE); |
195 if (key.Valid()) { | 213 if (key.Valid()) { |
214 | |
196 key.ReadValueDW(L"PreReadSize", &pre_read_size); | 215 key.ReadValueDW(L"PreReadSize", &pre_read_size); |
216 key.ReadValueDW(L"PreReadPercentage", &pre_read_percentage); | |
chrisha
2012/02/03 16:31:08
ubernit: Keep these in alphabetic order?
Roger McFarlane (Chromium)
2012/02/03 17:45:42
Done. Also only read the sizes and percentage if t
| |
197 key.ReadValueDW(L"PreReadStepSize", &pre_read_step_size); | 217 key.ReadValueDW(L"PreReadStepSize", &pre_read_step_size); |
198 key.ReadValueDW(L"PreRead", &pre_read); | 218 use_registry = (key.ReadValueDW(L"PreRead", &pre_read) == ERROR_SUCCESS); |
199 key.Close(); | 219 key.Close(); |
200 } | 220 } |
201 | 221 |
202 #if defined(OS_WIN) | 222 #if defined(OS_WIN) |
203 #if defined(GOOGLE_CHROME_BUILD) | 223 #if defined(GOOGLE_CHROME_BUILD) |
204 // The PreRead experiment is unable to use the standard FieldTrial | 224 // The PreRead experiment is unable to use the standard FieldTrial |
205 // mechanism as pre-reading happens in chrome.exe prior to loading | 225 // mechanism as pre-reading happens in chrome.exe prior to loading |
206 // chrome.dll. As such, we use a custom approach. If the experiment is | 226 // chrome.dll. As such, we use a custom approach. If the experiment is |
207 // running (not expired, and we're running a version of chrome from an | 227 // running (not expired, and we're running a version of chrome from an |
208 // appropriate channel) then we look to the registry for the BreakPad/UMA | 228 // appropriate channel) then we look to the registry for the BreakPad/UMA |
209 // metricsid. We use this to seed a coin-toss, which is then communicated | 229 // metricsid. We use this to seed a coin-toss, which is then communicated |
210 // to chrome.dll via an environment variable, which indicates to chrome.dll | 230 // to chrome.dll via an environment variable, which indicates to chrome.dll |
211 // that the experiment is running, causing it to report sub-histogram | 231 // that the experiment is running, causing it to report sub-histogram |
212 // results. | 232 // results. |
213 | 233 // |
234 // If we've read pre-read settings from the registry, then someone has | |
235 // specificaly set their pre-read options and is not participating in | |
Sigurður Ásgeirsson
2012/02/03 16:36:39
nit: specificaly->specifically
Roger McFarlane (Chromium)
2012/02/03 17:45:42
Done.
| |
236 // the experiment. | |
237 // | |
214 // If the experiment is running, indicate it to chrome.dll via an | 238 // If the experiment is running, indicate it to chrome.dll via an |
215 // environment variable. | 239 // environment variable. A pre_read value of 1 indicates that a full |
216 if (GetPreReadExperimentGroup(&pre_read)) { | 240 // (100%, the current default behaviour) pre-read is to be performed, |
241 // while a pre_read value of 0 indicates a partial pre-read is to be | |
242 // performed, up to the configured percentage. | |
243 if (!use_registry && GetPreReadExperimentGroup(&pre_read)) { | |
217 DCHECK(pre_read == 0 || pre_read == 1); | 244 DCHECK(pre_read == 0 || pre_read == 1); |
218 scoped_ptr<base::Environment> env(base::Environment::Create()); | 245 scoped_ptr<base::Environment> env(base::Environment::Create()); |
219 env->SetVar(chrome::kPreReadEnvironmentVariable, | 246 env->SetVar(chrome::kPreReadEnvironmentVariable, |
220 pre_read ? "1" : "0"); | 247 pre_read ? "1" : "0"); |
248 pre_read_percentage = kPreReadPercentage; | |
221 } | 249 } |
222 #endif // if defined(GOOGLE_CHROME_BUILD) | 250 #endif // if defined(GOOGLE_CHROME_BUILD) |
223 #endif // if defined(OS_WIN) | 251 #endif // if defined(OS_WIN) |
224 | 252 |
225 if (pre_read) { | 253 // Clamp the DWORD percentage to fit into a uint8 that's <= 100. |
226 TRACE_EVENT_BEGIN_ETW("PreReadImage", 0, ""); | 254 uint8 percentage_to_read = static_cast<uint8>( |
227 file_util::PreReadImage(dir->c_str(), pre_read_size, pre_read_step_size); | 255 std::min<DWORD>(pre_read ? 100 : pre_read_percentage, 100) & 0xFF); |
chrisha
2012/02/03 16:31:08
The & 0xFF is redundant at this point, given the c
Roger McFarlane (Chromium)
2012/02/03 17:45:42
Done.
| |
228 TRACE_EVENT_END_ETW("PreReadImage", 0, ""); | 256 |
229 } | 257 // Perform the full or partial pre-read. |
258 TRACE_EVENT_BEGIN_ETW("PreReadImage", 0, ""); | |
259 ImagePreReader::PartialPreReadImage(dir->c_str(), | |
260 percentage_to_read, | |
261 pre_read_step_size); | |
262 TRACE_EVENT_END_ETW("PreReadImage", 0, ""); | |
chrisha
2012/02/03 16:31:08
Leave this surrounded by the "if (pre_read && perc
Roger McFarlane (Chromium)
2012/02/03 17:45:42
So that's not quite the way the experiment works n
| |
230 } | 263 } |
231 #endif // NDEBUG | 264 #endif // NDEBUG |
232 #endif // WIN_DISABLE_PREREAD | 265 #endif // WIN_DISABLE_PREREAD |
233 | 266 |
234 return ::LoadLibraryExW(dir->c_str(), NULL, | 267 return ::LoadLibraryExW(dir->c_str(), NULL, |
235 LOAD_WITH_ALTERED_SEARCH_PATH); | 268 LOAD_WITH_ALTERED_SEARCH_PATH); |
236 } | 269 } |
237 | 270 |
238 void RecordDidRun(const std::wstring& dll_path) { | 271 void RecordDidRun(const std::wstring& dll_path) { |
239 bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str()); | 272 bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str()); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 } | 425 } |
393 }; | 426 }; |
394 | 427 |
395 MainDllLoader* MakeMainDllLoader() { | 428 MainDllLoader* MakeMainDllLoader() { |
396 #if defined(GOOGLE_CHROME_BUILD) | 429 #if defined(GOOGLE_CHROME_BUILD) |
397 return new ChromeDllLoader(); | 430 return new ChromeDllLoader(); |
398 #else | 431 #else |
399 return new ChromiumDllLoader(); | 432 return new ChromiumDllLoader(); |
400 #endif | 433 #endif |
401 } | 434 } |
OLD | NEW |