Chromium Code Reviews| 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 |