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 "chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h" | 5 #include "chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h" |
| 6 | 6 |
| 7 #include "base/sys_info.h" | 7 #include "base/sys_info.h" |
| 8 #include "content/public/browser/browser_thread.h" | |
| 8 | 9 |
| 9 namespace extensions { | 10 namespace extensions { |
| 10 | 11 |
| 11 using api::experimental_system_info_cpu::CpuInfo; | 12 using api::experimental_system_info_cpu::CpuInfo; |
| 13 using api::experimental_system_info_cpu::CpuUpdateInfo; | |
| 14 using content::BrowserThread; | |
| 15 | |
| 16 // Default sampling interval is 1000ms. | |
| 17 const unsigned int kDefaultSamplingIntervalMs = 1000; | |
| 18 | |
| 19 CpuInfoProvider::CpuInfoProvider() | |
| 20 : is_sampling_started_(false), | |
| 21 sampling_timer_(NULL), | |
| 22 sampling_interval_(kDefaultSamplingIntervalMs) { | |
| 23 } | |
| 24 | |
| 25 CpuInfoProvider::~CpuInfoProvider() { | |
| 26 if (sampling_timer_) | |
| 27 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, sampling_timer_); | |
|
benwells
2012/09/21 08:19:50
This feels racy. Can the timer fire before it is d
Hongbo Min
2012/09/21 09:00:23
Your concern is valid, but if the CpuInfoProvider
benwells
2012/09/25 17:32:13
Lazy instances are destroyed at program exit. I do
| |
| 28 } | |
| 12 | 29 |
| 13 bool CpuInfoProvider::QueryInfo(CpuInfo* info) { | 30 bool CpuInfoProvider::QueryInfo(CpuInfo* info) { |
| 14 if (info == NULL) | 31 if (info == NULL) |
| 15 return false; | 32 return false; |
| 16 | 33 |
| 17 info->num_of_processors = base::SysInfo::NumberOfProcessors(); | 34 info->num_of_processors = base::SysInfo::NumberOfProcessors(); |
| 18 info->arch_name = base::SysInfo::CPUArchitecture(); | 35 info->arch_name = base::SysInfo::CPUArchitecture(); |
| 19 info->model_name = base::SysInfo::CPUModelName(); | 36 info->model_name = base::SysInfo::CPUModelName(); |
| 20 return true; | 37 return true; |
| 21 } | 38 } |
| 22 | 39 |
| 23 bool CpuInfoProvider::StartSampling(const QueryCpuTimeCallback& callback) { | 40 void CpuInfoProvider::StartSampling(const SamplingCallback& callback) { |
| 24 // TODO(hongbo): Implement sampling functionality for event router. | 41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 25 return false; | 42 BrowserThread::PostTask( |
| 43 BrowserThread::FILE, | |
| 44 FROM_HERE, | |
| 45 base::Bind(&CpuInfoProvider::StartSamplingOnFileThread, | |
| 46 base::Unretained(this), callback)); | |
| 26 } | 47 } |
| 27 | 48 |
| 28 bool CpuInfoProvider::StopSampling() { | 49 void CpuInfoProvider::StopSampling() { |
| 29 // TODO(hongbo): Implement sampling functionality for event router. | 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 30 return false; | 51 BrowserThread::PostTask( |
| 52 BrowserThread::FILE, | |
| 53 FROM_HERE, | |
| 54 base::Bind(&CpuInfoProvider::StopSamplingOnFileThread, | |
| 55 base::Unretained(this))); | |
|
benwells
2012/09/21 08:19:50
Why use unretained here? If you descend from RefCo
Hongbo Min
2012/09/21 09:00:23
The CpuInfoProvider is a global lazy instance and
benwells
2012/09/25 17:32:13
OK, again if you ensure the timer is stopped when
| |
| 31 } | 56 } |
| 32 | 57 |
| 33 // static | 58 // static |
| 34 CpuInfoProvider* CpuInfoProvider::Get() { | 59 CpuInfoProvider* CpuInfoProvider::Get() { |
| 35 return CpuInfoProvider::GetInstance<CpuInfoProvider>(); | 60 return CpuInfoProvider::GetInstance<CpuInfoProvider>(); |
| 36 } | 61 } |
| 37 | 62 |
| 63 void CpuInfoProvider::StartSamplingOnFileThread( | |
| 64 const SamplingCallback& callback) { | |
| 65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 66 if (is_sampling_started_) | |
| 67 return; | |
| 68 | |
| 69 if (!QueryCpuTimePerProcessor(&baseline_cpu_time_)) | |
| 70 return; | |
| 71 | |
| 72 is_sampling_started_ = true; | |
| 73 callback_ = callback; | |
| 74 DCHECK(!sampling_timer_) << "The sampling timer is leaked. Did you forgot " | |
| 75 "calling StopSampling?"; | |
| 76 // Should be deleted on FILE thread. | |
| 77 sampling_timer_ = new base::RepeatingTimer<CpuInfoProvider>(); | |
| 78 sampling_timer_->Start(FROM_HERE, | |
| 79 base::TimeDelta::FromMilliseconds(sampling_interval_), | |
| 80 this, &CpuInfoProvider::DoSample); | |
| 81 } | |
| 82 | |
| 83 void CpuInfoProvider::StopSamplingOnFileThread() { | |
| 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 85 if (!is_sampling_started_) return; | |
| 86 delete sampling_timer_; | |
| 87 sampling_timer_ = NULL; | |
| 88 baseline_cpu_time_.clear(); | |
| 89 is_sampling_started_ = false; | |
| 90 } | |
| 91 | |
| 92 void CpuInfoProvider::DoSample() { | |
| 93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 94 | |
| 95 std::vector<CpuTime> next_cpu_time; | |
| 96 if (!QueryCpuTimePerProcessor(&next_cpu_time)) | |
| 97 return; | |
| 98 | |
| 99 // Calculate the CPU usage information from the next_cpu_time and | |
| 100 // |baseline_cpu_time_|. | |
| 101 double total_usage = 0; | |
| 102 scoped_ptr<CpuUpdateInfo> info(new CpuUpdateInfo()); | |
| 103 for (size_t i = 0; i < next_cpu_time.size(); ++i) { | |
| 104 double total_time = | |
| 105 (next_cpu_time[i].user - baseline_cpu_time_[i].user) + | |
| 106 (next_cpu_time[i].kernel - baseline_cpu_time_[i].kernel) + | |
| 107 (next_cpu_time[i].idle - baseline_cpu_time_[i].idle); | |
| 108 double idle_time = next_cpu_time[i].idle - baseline_cpu_time_[i].idle; | |
| 109 | |
| 110 double usage = 0; | |
| 111 if (total_time != 0) | |
| 112 usage = (100 - idle_time * 100 / total_time); | |
| 113 info->usage_per_processor.push_back(usage); | |
| 114 total_usage += usage; | |
| 115 } | |
| 116 | |
| 117 info->average_usage = total_usage / next_cpu_time.size(); | |
| 118 if (!callback_.is_null()) | |
| 119 callback_.Run(info.Pass()); | |
| 120 // Use next_cpu_time as baseline_cpu_time_ for the next sampling cycle. | |
| 121 baseline_cpu_time_.swap(next_cpu_time); | |
| 122 } | |
| 123 | |
| 38 } // namespace extensions | 124 } // namespace extensions |
| OLD | NEW |