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()) { |
196 key.ReadValueDW(L"PreReadSize", &pre_read_size); | 214 use_registry = (key.ReadValueDW(L"PreRead", &pre_read) == ERROR_SUCCESS); |
197 key.ReadValueDW(L"PreReadStepSize", &pre_read_step_size); | 215 if (use_registry) { |
198 key.ReadValueDW(L"PreRead", &pre_read); | 216 key.ReadValueDW(L"PreReadPercentage", &pre_read_percentage); |
| 217 key.ReadValueDW(L"PreReadSize", &pre_read_size); |
| 218 key.ReadValueDW(L"PreReadStepSize", &pre_read_step_size); |
| 219 } |
199 key.Close(); | 220 key.Close(); |
200 } | 221 } |
201 | 222 |
202 #if defined(OS_WIN) | 223 #if defined(OS_WIN) |
203 #if defined(GOOGLE_CHROME_BUILD) | 224 #if defined(GOOGLE_CHROME_BUILD) |
204 // The PreRead experiment is unable to use the standard FieldTrial | 225 // The PreRead experiment is unable to use the standard FieldTrial |
205 // mechanism as pre-reading happens in chrome.exe prior to loading | 226 // 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 | 227 // 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 | 228 // 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 | 229 // 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 | 230 // 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 | 231 // to chrome.dll via an environment variable, which indicates to chrome.dll |
211 // that the experiment is running, causing it to report sub-histogram | 232 // that the experiment is running, causing it to report sub-histogram |
212 // results. | 233 // results. |
213 | 234 // |
| 235 // If we've read pre-read settings from the registry, then someone has |
| 236 // specifically set their pre-read options and is not participating in |
| 237 // the experiment. |
| 238 // |
214 // If the experiment is running, indicate it to chrome.dll via an | 239 // If the experiment is running, indicate it to chrome.dll via an |
215 // environment variable. | 240 // environment variable. A pre_read value of 1 indicates that a full |
216 if (GetPreReadExperimentGroup(&pre_read)) { | 241 // (100%, the current default behaviour) pre-read is to be performed, |
| 242 // while a pre_read value of 0 indicates a partial pre-read is to be |
| 243 // performed, up to the configured percentage. |
| 244 if (!use_registry && GetPreReadExperimentGroup(&pre_read)) { |
217 DCHECK(pre_read == 0 || pre_read == 1); | 245 DCHECK(pre_read == 0 || pre_read == 1); |
218 scoped_ptr<base::Environment> env(base::Environment::Create()); | 246 scoped_ptr<base::Environment> env(base::Environment::Create()); |
219 env->SetVar(chrome::kPreReadEnvironmentVariable, | 247 env->SetVar(chrome::kPreReadEnvironmentVariable, |
220 pre_read ? "1" : "0"); | 248 pre_read ? "1" : "0"); |
| 249 pre_read_percentage = kPreReadPercentage; |
221 } | 250 } |
222 #endif // if defined(GOOGLE_CHROME_BUILD) | 251 #endif // if defined(GOOGLE_CHROME_BUILD) |
223 #endif // if defined(OS_WIN) | 252 #endif // if defined(OS_WIN) |
224 | 253 |
225 if (pre_read) { | 254 // Clamp the DWORD percentage to fit into a uint8 that's <= 100. |
226 TRACE_EVENT_BEGIN_ETW("PreReadImage", 0, ""); | 255 uint8 percentage_to_read = static_cast<uint8>( |
227 file_util::PreReadImage(dir->c_str(), pre_read_size, pre_read_step_size); | 256 std::min<DWORD>(pre_read ? 100 : pre_read_percentage, 100)); |
228 TRACE_EVENT_END_ETW("PreReadImage", 0, ""); | 257 |
229 } | 258 // Perform the full or partial pre-read. |
| 259 TRACE_EVENT_BEGIN_ETW("PreReadImage", 0, ""); |
| 260 ImagePreReader::PartialPreReadImage(dir->c_str(), |
| 261 percentage_to_read, |
| 262 pre_read_step_size); |
| 263 TRACE_EVENT_END_ETW("PreReadImage", 0, ""); |
230 } | 264 } |
231 #endif // NDEBUG | 265 #endif // NDEBUG |
232 #endif // WIN_DISABLE_PREREAD | 266 #endif // WIN_DISABLE_PREREAD |
233 | 267 |
234 return ::LoadLibraryExW(dir->c_str(), NULL, | 268 return ::LoadLibraryExW(dir->c_str(), NULL, |
235 LOAD_WITH_ALTERED_SEARCH_PATH); | 269 LOAD_WITH_ALTERED_SEARCH_PATH); |
236 } | 270 } |
237 | 271 |
238 void RecordDidRun(const std::wstring& dll_path) { | 272 void RecordDidRun(const std::wstring& dll_path) { |
239 bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str()); | 273 bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str()); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 } | 426 } |
393 }; | 427 }; |
394 | 428 |
395 MainDllLoader* MakeMainDllLoader() { | 429 MainDllLoader* MakeMainDllLoader() { |
396 #if defined(GOOGLE_CHROME_BUILD) | 430 #if defined(GOOGLE_CHROME_BUILD) |
397 return new ChromeDllLoader(); | 431 return new ChromeDllLoader(); |
398 #else | 432 #else |
399 return new ChromiumDllLoader(); | 433 return new ChromiumDllLoader(); |
400 #endif | 434 #endif |
401 } | 435 } |
OLD | NEW |