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

Side by Side Diff: chrome/app/client_util.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: Declare all of the experiment groups... and other refactorings. 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 <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_version_info.h" 11 #include "base/file_version_info.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.
15 #include "base/sha1.h" // For PreRead experiment.
14 #include "base/strings/string16.h" 16 #include "base/strings/string16.h"
15 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
18 #include "base/version.h" 20 #include "base/version.h"
19 #include "base/win/windows_version.h" 21 #include "base/win/windows_version.h"
20 #include "chrome/app/breakpad_win.h" 22 #include "chrome/app/breakpad_win.h"
21 #include "chrome/app/client_util.h" 23 #include "chrome/app/client_util.h"
22 #include "chrome/app/image_pre_reader_win.h" 24 #include "chrome/app/image_pre_reader_win.h"
23 #include "chrome/common/chrome_constants.h" 25 #include "chrome/common/chrome_constants.h"
24 #include "chrome/common/chrome_result_codes.h" 26 #include "chrome/common/chrome_result_codes.h"
25 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/env_vars.h" 28 #include "chrome/common/env_vars.h"
27 #include "chrome/installer/util/browser_distribution.h" 29 #include "chrome/installer/util/browser_distribution.h"
28 #include "chrome/installer/util/channel_info.h" 30 #include "chrome/installer/util/channel_info.h"
29 #include "chrome/installer/util/google_update_constants.h" 31 #include "chrome/installer/util/google_update_constants.h"
30 #include "chrome/installer/util/google_update_settings.h" 32 #include "chrome/installer/util/google_update_settings.h"
31 #include "chrome/installer/util/install_util.h" 33 #include "chrome/installer/util/install_util.h"
32 #include "chrome/installer/util/util_constants.h" 34 #include "chrome/installer/util/util_constants.h"
33 35
34 namespace { 36 namespace {
35 // The entry point signature of chrome.dll. 37 // The entry point signature of chrome.dll.
36 typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*); 38 typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*);
37 39
38 typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)(); 40 typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)();
39 41
42 bool PreReadExpirementHasExpired() {
43 static const int kPreReadExpiryYear = 2014;
44 static const int kPreReadExpiryMonth = 7;
45 static const int kPreReadExpiryDay = 1;
46 static const char kBuildTimeStr[] = __DATE__ " " __TIME__;
47
48 // Get the timestamp of the build.
49 base::Time build_time;
50 bool result = base::Time::FromString(kBuildTimeStr, &build_time);
51 DCHECK(result);
52
53 // Get the timestamp at which the experiment expires.
54 base::Time::Exploded exploded = {0};
55 exploded.year = kPreReadExpiryYear;
56 exploded.month = kPreReadExpiryMonth;
57 exploded.day_of_month = kPreReadExpiryDay;
58 base::Time expiration_time = base::Time::FromLocalExploded(exploded);
59
60 // Return true if the experiment is expired.
61 return (build_time > expiration_time);
Alexei Svitkine (slow) 2013/08/29 17:44:05 Nit: No ()'s needed.
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
62 }
63
64 void GetRandomPopulationAndGroup(double* population, double* group) {
Alexei Svitkine (slow) 2013/08/29 17:44:05 Add a comment explaining what this does (and the o
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
65 DCHECK(population != NULL);
66 DCHECK(group != NULL);
67
68 // Use the metrics id for the user as stable pseudo-random input to a hash.
69 base::string16 key;
70 GoogleUpdateSettings::GetMetricsId(&key);
Roger McFarlane (Chromium) 2013/08/29 15:28:37 Fall back to something like the MAC address is the
Alexei Svitkine (slow) 2013/08/29 17:44:05 Hmm, it is unfortunate that you need this to be pe
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Per your suggestion: if I don't have the metrics i
71
72 // To interpret the key as a random number we hash it and intepret the first
chrisha 2013/08/29 15:52:19 interpret*
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
73 // 8 bytes of it as a unit-interval representing a die-toss for being in the
74 // experiment population and the second 8 bytes as a die-toss for being in
75 // various experiment groups.
76 unsigned char sha1_hash[base::kSHA1Length];
77 base::SHA1HashBytes(
78 reinterpret_cast<const unsigned char*>(key.c_str()),
79 key.size() * sizeof(key[0]),
80 sha1_hash);
81 COMPILE_ASSERT(2 * sizeof(uint64) < sizeof(sha1_hash), need_more_data);
82 const uint64* population_bits = reinterpret_cast<uint64*>(&sha1_hash[0]);
83 const uint64* group_bits = population_bits + 1;
Alexei Svitkine (slow) 2013/08/29 17:44:05 I think it would be slightly clearer to keep a sin
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
84
85 // Convert the bits into unit-intervals and return.
86 *population = base::BitsToOpenEndedUnitInterval(*population_bits);
87 *group = base::BitsToOpenEndedUnitInterval(*group_bits);
88 }
89
90 uint8 GetPreReadPercentage() {
91 // By default use the old behaviour: read 100%.
92 static const uint8 kDefaultPercentage = 100;
93 static const char kDefaultFormatStr[] = "%d%%-Default";
94 static const char kControlFormatStr[] = "%d%%-Control";
95 static const char kGroupFormatStr[] = "%d%%";
96
97 COMPILE_ASSERT(kDefaultPercentage <= 100, default_percentage_too_large);
98 COMPILE_ASSERT(kDefaultPercentage % 5 == 0, default_percentage_not_mult_5);
99
100 scoped_ptr<base::Environment> env(base::Environment::Create());
101
102 // If the expirement has expired use the default pre-read level.
chrisha 2013/08/29 15:52:19 experiment*
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
103 if (PreReadExpirementHasExpired()) {
104 env->SetVar(chrome::kPreReadEnvironmentVariable,
105 base::StringPrintf(kDefaultFormatStr, kDefaultPercentage));
106 return kDefaultPercentage;
107 }
108
109 // Roll the dice to determine if this user is in the experiment and if so,
110 // in which experimental group.
111 double population = 0.0;
112 double group = 0.0;
113 GetRandomPopulationAndGroup(&population, &group);
114
115 // We limit experiment populations to 1% of the Stable and 10% of the Beta
116 // and Dev channels.
117 const string16 channel(GoogleUpdateSettings::GetChromeChannel(
118 GoogleUpdateSettings::IsSystemInstall()));
119 if ((channel == installer::kChromeChannelStable && population > 0.01) ||
120 ((channel == installer::kChromeChannelBeta ||
Alexei Svitkine (slow) 2013/08/29 17:44:05 Instead of checking for the other channels explici
121 channel == installer::kChromeChannelDev) && population > 0.10)) {
122 env->SetVar(chrome::kPreReadEnvironmentVariable,
123 base::StringPrintf(kDefaultFormatStr, kDefaultPercentage));
124 return kDefaultPercentage;
125 }
126
127 // We divide the experiment population into groups pre-reading at 5 percent
128 // increments. This is 21 groups of 5 -- to include the range [100, 105) --
129 // rounded down to the nearest 5.
130 uint8 percentage = static_cast<uint8>(group * 21.0) * 5;
Alexei Svitkine (slow) 2013/08/29 17:44:05 Use a size_t instead.
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
131 DCHECK_GE(100, percentage);
chrisha 2013/08/29 15:52:19 100u?
Alexei Svitkine (slow) 2013/08/29 17:44:05 For macros like _GE, the literal doesn't have to b
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
132 DCHECK_EQ(0, percentage % 5);
chrisha 2013/08/29 15:52:19 0u?
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
133
134 const char* format_str =
135 (percentage == kDefaultPercentage) ? kControlFormatStr : kGroupFormatStr;
136
137 env->SetVar(chrome::kPreReadEnvironmentVariable,
138 base::StringPrintf(format_str, percentage));
Alexei Svitkine (slow) 2013/08/29 17:44:05 I think it would be cleaner for this function to n
Roger McFarlane (Chromium) 2013/08/30 21:27:37 I've refactored it a bit. Is this better? I'd rat
139
140 return percentage;
141 }
142
40 // Expects that |dir| has a trailing backslash. |dir| is modified so it 143 // Expects that |dir| has a trailing backslash. |dir| is modified so it
41 // contains the full path that was tried. Caller must check for the return 144 // contains the full path that was tried. Caller must check for the return
42 // value not being null to determine if this path contains a valid dll. 145 // value not being null to determine if this path contains a valid dll.
43 HMODULE LoadChromeWithDirectory(string16* dir) { 146 HMODULE LoadChromeWithDirectory(string16* dir) {
44 ::SetCurrentDirectoryW(dir->c_str()); 147 ::SetCurrentDirectoryW(dir->c_str());
45 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); 148 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
46 #if !defined(CHROME_MULTIPLE_DLL) 149 #if !defined(CHROME_MULTIPLE_DLL)
47 const wchar_t* dll_name = installer::kChromeDll; 150 const wchar_t* dll_name = installer::kChromeDll;
48 #else 151 #else
49 const wchar_t* dll_name = cmd_line.HasSwitch(switches::kProcessType) ? 152 const wchar_t* dll_name = cmd_line.HasSwitch(switches::kProcessType) ?
50 installer::kChromeChildDll : installer::kChromeDll; 153 installer::kChromeChildDll : installer::kChromeDll;
51 #endif 154 #endif
52 dir->append(dll_name); 155 dir->append(dll_name);
53 156
54 #if !defined(WIN_DISABLE_PREREAD) 157 #if !defined(WIN_DISABLE_PREREAD)
55 // On Win7 with Syzygy, pre-read is a win. There've very little difference 158 // On Win7 with Syzygy, pre-read is a win. There've very little difference
56 // between 25% and 100%. For cold starts, with or without prefetch 25% 159 // between 25% and 100%. For cold starts, with or without prefetch 25%
57 // performs slightly better than 100%. On XP, pre-read is generally a 160 // performs slightly better than 100%. On XP, pre-read is generally a
58 // performance loss. 161 // performance loss.
59 if (!cmd_line.HasSwitch(switches::kProcessType)) { 162 if (!cmd_line.HasSwitch(switches::kProcessType)) {
60 const size_t kStepSize = 1024 * 1024; 163 static const size_t kStepSize = 1024 * 1024;
Alexei Svitkine (slow) 2013/08/29 17:44:05 Nit: No need for static.
Roger McFarlane (Chromium) 2013/08/30 21:27:37 Done.
61 uint8 percent = base::win::GetVersion() > base::win::VERSION_XP ? 25 : 0; 164 uint8 percentage = GetPreReadPercentage();
62 ImagePreReader::PartialPreReadImage(dir->c_str(), percent, kStepSize); 165 ImagePreReader::PartialPreReadImage(dir->c_str(), percentage, kStepSize);
63 } 166 }
64 #endif 167 #endif
65 168
66 return ::LoadLibraryExW(dir->c_str(), NULL, 169 return ::LoadLibraryExW(dir->c_str(), NULL,
67 LOAD_WITH_ALTERED_SEARCH_PATH); 170 LOAD_WITH_ALTERED_SEARCH_PATH);
68 } 171 }
69 172
70 void RecordDidRun(const string16& dll_path) { 173 void RecordDidRun(const string16& dll_path) {
71 bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str()); 174 bool system_level = !InstallUtil::IsPerUserInstall(dll_path.c_str());
72 GoogleUpdateSettings::UpdateDidRunState(true, system_level); 175 GoogleUpdateSettings::UpdateDidRunState(true, system_level);
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 } 341 }
239 }; 342 };
240 343
241 MainDllLoader* MakeMainDllLoader() { 344 MainDllLoader* MakeMainDllLoader() {
242 #if defined(GOOGLE_CHROME_BUILD) 345 #if defined(GOOGLE_CHROME_BUILD)
243 return new ChromeDllLoader(); 346 return new ChromeDllLoader();
244 #else 347 #else
245 return new ChromiumDllLoader(); 348 return new ChromiumDllLoader();
246 #endif 349 #endif
247 } 350 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698