Index: chrome/browser/metrics/perf_provider_chromeos.cc |
diff --git a/chrome/browser/metrics/perf_provider_chromeos.cc b/chrome/browser/metrics/perf_provider_chromeos.cc |
index efa0d00dea7efbfa886af51959877dc2879316c9..5afa098bb896d78b9fb0a9497695ea1d84d0feeb 100644 |
--- a/chrome/browser/metrics/perf_provider_chromeos.cc |
+++ b/chrome/browser/metrics/perf_provider_chromeos.cc |
@@ -24,26 +24,10 @@ |
namespace { |
-// Default time in seconds between invocations of perf. |
-// This period is roughly 6.5 hours. |
-// This is chosen to be relatively prime with the number of seconds in: |
-// - one minute (60) |
-// - one hour (3600) |
-// - one day (86400) |
-const size_t kPerfCommandIntervalDefaultSeconds = 23093; |
- |
-// The first collection interval is different from the interval above. This is |
-// because we want to collect the first profile quickly after Chrome is started. |
-// If this period is too long, the user will log off and Chrome will be killed |
-// before it is triggered. The following 2 variables determine the upper and |
-// lower bound on the interval. |
-// The reason we do not always want to collect the initial profile after a fixed |
-// period is to not over-represent task X in the profile where task X always |
-// runs at a fixed period after start-up. By selecting a period randomly between |
-// a lower and upper bound, we will hopefully collect a more fair profile. |
-const size_t kPerfCommandStartIntervalLowerBoundMinutes = 10; |
- |
-const size_t kPerfCommandStartIntervalUpperBoundMinutes = 20; |
+// Partition time since login into successive intervals of this size. In each |
+// interval, pick a random time to collect a profile. |
+// This interval is twenty-four hours. |
+const size_t kPerfProfilingIntervalMs = 24 * 60 * 60 * 1000; |
// Default time in seconds perf is run for. |
const size_t kPerfCommandDurationDefaultSeconds = 2; |
@@ -119,6 +103,7 @@ class WindowedIncognitoObserver : public chrome::BrowserListObserver { |
PerfProvider::PerfProvider() |
: login_observer_(this), |
+ next_profiling_interval_start_(base::TimeTicks::Now()), |
weak_factory_(this) { |
// Register the login observer with LoginState. |
chromeos::LoginState::Get()->AddObserver(&login_observer_); |
@@ -135,14 +120,15 @@ PerfProvider::~PerfProvider() { |
chromeos::LoginState::Get()->RemoveObserver(&login_observer_); |
} |
-bool PerfProvider::GetPerfData(std::vector<PerfDataProto>* perf_data) { |
+bool PerfProvider::GetSampledProfiles( |
+ std::vector<SampledProfile>* sampled_profiles) { |
DCHECK(CalledOnValidThread()); |
if (cached_perf_data_.empty()) { |
AddToPerfHistogram(NOT_READY_TO_UPLOAD); |
return false; |
} |
- perf_data->swap(cached_perf_data_); |
+ sampled_profiles->swap(cached_perf_data_); |
cached_perf_data_.clear(); |
AddToPerfHistogram(SUCCESS); |
@@ -154,16 +140,14 @@ PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider) |
void PerfProvider::LoginObserver::LoggedInStateChanged() { |
if (IsNormalUserLoggedIn()) |
- perf_provider_->Activate(); |
+ perf_provider_->OnUserLoggedIn(); |
else |
perf_provider_->Deactivate(); |
} |
-void PerfProvider::Activate() { |
- size_t collection_interval_minutes = base::RandInt( |
- kPerfCommandStartIntervalLowerBoundMinutes, |
- kPerfCommandStartIntervalUpperBoundMinutes); |
- ScheduleCollection(base::TimeDelta::FromMinutes(collection_interval_minutes)); |
+void PerfProvider::OnUserLoggedIn() { |
+ login_time_ = base::TimeTicks::Now(); |
+ ScheduleCollection(); |
} |
void PerfProvider::Deactivate() { |
@@ -171,16 +155,33 @@ void PerfProvider::Deactivate() { |
timer_.Stop(); |
} |
-void PerfProvider::ScheduleCollection(const base::TimeDelta& interval) { |
+void PerfProvider::ScheduleCollection() { |
DCHECK(CalledOnValidThread()); |
if (timer_.IsRunning()) |
return; |
- timer_.Start(FROM_HERE, interval, this, |
- &PerfProvider::CollectIfNecessaryAndReschedule); |
+ // Pick a random time in the current interval. |
+ base::TimeTicks scheduled_time = |
+ next_profiling_interval_start_ + |
+ base::TimeDelta::FromMilliseconds( |
+ base::RandGenerator(kPerfProfilingIntervalMs)); |
+ |
+ // If the scheduled time has already passed in the time it took to make the |
+ // above calculations, trigger the collection event immediately. |
+ base::TimeTicks now = base::TimeTicks::Now(); |
+ if (scheduled_time < now) |
+ scheduled_time = now; |
+ |
+ timer_.Start(FROM_HERE, scheduled_time - now, this, |
+ &PerfProvider::DoPeriodicCollection); |
+ |
+ // Update the profiling interval tracker to the start of the next interval. |
+ next_profiling_interval_start_ += |
+ base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs); |
} |
-void PerfProvider::CollectIfNecessary() { |
+void PerfProvider::CollectIfNecessary( |
+ SampledProfile::TriggerEvent trigger_event) { |
DCHECK(CalledOnValidThread()); |
// Do not collect further data if we've already collected a substantial amount |
@@ -213,17 +214,18 @@ void PerfProvider::CollectIfNecessary() { |
client->GetPerfData(collection_duration.InSeconds(), |
base::Bind(&PerfProvider::ParseProtoIfValid, |
weak_factory_.GetWeakPtr(), |
- base::Passed(&incognito_observer))); |
+ base::Passed(&incognito_observer), |
+ trigger_event)); |
} |
-void PerfProvider::CollectIfNecessaryAndReschedule() { |
- CollectIfNecessary(); |
- ScheduleCollection( |
- base::TimeDelta::FromSeconds(kPerfCommandIntervalDefaultSeconds)); |
+void PerfProvider::DoPeriodicCollection() { |
+ CollectIfNecessary(SampledProfile::PERIODIC_COLLECTION); |
+ ScheduleCollection(); |
} |
void PerfProvider::ParseProtoIfValid( |
scoped_ptr<WindowedIncognitoObserver> incognito_observer, |
+ SampledProfile::TriggerEvent trigger_event, |
const std::vector<uint8>& data) { |
DCHECK(CalledOnValidThread()); |
@@ -238,10 +240,19 @@ void PerfProvider::ParseProtoIfValid( |
return; |
} |
- // Append a new PerfDataProto to the |cached_perf_data_| vector and swap in |
- // the contents. |
+ // Populate a profile collection protobuf with the collected perf data and |
+ // extra metadata. |
cached_perf_data_.resize(cached_perf_data_.size() + 1); |
- cached_perf_data_.back().Swap(&perf_data_proto); |
+ SampledProfile& collection_data = cached_perf_data_.back(); |
+ collection_data.set_trigger_event(trigger_event); |
+ collection_data.set_ms_after_boot( |
+ perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond); |
+ |
+ DCHECK(!login_time_.is_null()); |
+ collection_data. |
+ set_ms_after_login((base::TimeTicks::Now() - login_time_) |
+ .InMilliseconds()); |
+ *collection_data.mutable_perf_data() = perf_data_proto; |
} |
} // namespace metrics |