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

Side by Side Diff: content/renderer/devtools/devtools_cpu_throttler.cc

Issue 2879313002: DevTools: More precise CPU throttling rate on Linux (Closed)
Patch Set: Created 3 years, 7 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "content/renderer/devtools/devtools_cpu_throttler.h" 5 #include "content/renderer/devtools/devtools_cpu_throttler.h"
6 6
7 #include "base/atomicops.h" 7 #include "base/atomicops.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "base/synchronization/cancellation_flag.h" 9 #include "base/synchronization/cancellation_flag.h"
10 #include "base/threading/platform_thread.h" 10 #include "base/threading/platform_thread.h"
(...skipping 28 matching lines...) Expand all
39 static void ResumeThread(base::PlatformThreadHandle thread_handle); 39 static void ResumeThread(base::PlatformThreadHandle thread_handle);
40 static void Sleep(base::TimeDelta duration); 40 static void Sleep(base::TimeDelta duration);
41 41
42 #ifdef USE_SIGNALS 42 #ifdef USE_SIGNALS
43 void InstallSignalHandler(); 43 void InstallSignalHandler();
44 void RestoreSignalHandler(); 44 void RestoreSignalHandler();
45 static void HandleSignal(int signal); 45 static void HandleSignal(int signal);
46 46
47 static bool signal_handler_installed_; 47 static bool signal_handler_installed_;
48 static struct sigaction old_signal_handler_; 48 static struct sigaction old_signal_handler_;
49 static Atomic32 suspended_;
50 #endif 49 #endif
51 static Atomic32 thread_exists_; 50 static Atomic32 thread_exists_;
51 static Atomic32 throttling_rate_percent_;
52 52
53 base::PlatformThreadHandle throttled_thread_handle_; 53 base::PlatformThreadHandle throttled_thread_handle_;
54 base::PlatformThreadHandle throttling_thread_handle_; 54 base::PlatformThreadHandle throttling_thread_handle_;
55 base::CancellationFlag cancellation_flag_; 55 base::CancellationFlag cancellation_flag_;
56 Atomic32 throttling_rate_percent_;
57 56
58 DISALLOW_COPY_AND_ASSIGN(CPUThrottlingThread); 57 DISALLOW_COPY_AND_ASSIGN(CPUThrottlingThread);
59 }; 58 };
60 59
61 #ifdef USE_SIGNALS 60 #ifdef USE_SIGNALS
62 bool CPUThrottlingThread::signal_handler_installed_; 61 bool CPUThrottlingThread::signal_handler_installed_;
63 struct sigaction CPUThrottlingThread::old_signal_handler_; 62 struct sigaction CPUThrottlingThread::old_signal_handler_;
64 Atomic32 CPUThrottlingThread::suspended_;
65 #endif 63 #endif
64 Atomic32 CPUThrottlingThread::throttling_rate_percent_;
66 Atomic32 CPUThrottlingThread::thread_exists_; 65 Atomic32 CPUThrottlingThread::thread_exists_;
67 66
68 CPUThrottlingThread::CPUThrottlingThread(double rate) 67 CPUThrottlingThread::CPUThrottlingThread(double rate)
69 #ifdef OS_WIN 68 #ifdef OS_WIN
70 : throttled_thread_handle_( 69 : throttled_thread_handle_(
71 ::OpenThread(THREAD_SUSPEND_RESUME, false, ::GetCurrentThreadId())), 70 ::OpenThread(THREAD_SUSPEND_RESUME, false, ::GetCurrentThreadId())) {
72 #else 71 #else
73 : throttled_thread_handle_(base::PlatformThread::CurrentHandle()), 72 : throttled_thread_handle_(base::PlatformThread::CurrentHandle()) {
74 #endif 73 #endif
75 throttling_rate_percent_(static_cast<Atomic32>(rate * 100)) { 74 SetThrottlingRate(rate);
76 CHECK(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 1) == 0); 75 CHECK(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 1) == 0);
77 Start(); 76 Start();
78 } 77 }
79 78
80 CPUThrottlingThread::~CPUThrottlingThread() { 79 CPUThrottlingThread::~CPUThrottlingThread() {
81 Stop(); 80 Stop();
82 CHECK(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 0) == 1); 81 CHECK(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 0) == 1);
83 } 82 }
84 83
85 void CPUThrottlingThread::SetThrottlingRate(double rate) { 84 void CPUThrottlingThread::SetThrottlingRate(double rate) {
(...skipping 26 matching lines...) Expand all
112 if (!signal_handler_installed_) 111 if (!signal_handler_installed_)
113 return; 112 return;
114 sigaction(SIGUSR2, &old_signal_handler_, 0); 113 sigaction(SIGUSR2, &old_signal_handler_, 0);
115 signal_handler_installed_ = false; 114 signal_handler_installed_ = false;
116 } 115 }
117 116
118 // static 117 // static
119 void CPUThrottlingThread::HandleSignal(int signal) { 118 void CPUThrottlingThread::HandleSignal(int signal) {
120 if (signal != SIGUSR2) 119 if (signal != SIGUSR2)
121 return; 120 return;
122 while (Acquire_Load(&suspended_)) { 121 static base::TimeTicks lastResumeTime;
123 } 122 base::TimeTicks now = base::TimeTicks::Now();
123 base::TimeDelta run_duration = now - lastResumeTime;
124 uint32_t throttling_rate_percent = Acquire_Load(&throttling_rate_percent_);
125 // Limit the observed run duration to 1000μs to deal with the first entrance
126 // to the signal handler.
127 uint32_t run_duration_us = static_cast<uint32_t>(
128 std::min(run_duration.InMicroseconds(), static_cast<int64_t>(1000)));
129 uint32_t sleep_duration_us =
130 run_duration_us * throttling_rate_percent / 100 - run_duration_us;
131 base::TimeTicks wake_up_time =
132 now + base::TimeDelta::FromMicroseconds(sleep_duration_us);
133 do {
134 now = base::TimeTicks::Now();
135 } while (now < wake_up_time);
136 lastResumeTime = now;
124 } 137 }
125 138
126 #endif // USE_SIGNALS 139 #endif // USE_SIGNALS
127 140
128 // static 141 void CPUThrottlingThread::Throttle() {
129 void CPUThrottlingThread::SuspendThread( 142 const int quant_time_us = 200;
130 base::PlatformThreadHandle thread_handle) { 143 #if defined(OS_WIN)
131 #if defined(USE_SIGNALS) 144 double rate = Acquire_Load(&throttling_rate_percent_) / 100.;
132 Release_Store(&suspended_, 1); 145 base::TimeDelta run_duration =
133 pthread_kill(thread_handle.platform_handle(), SIGUSR2); 146 base::TimeDelta::FromMicroseconds(static_cast<int>(quant_time_us / rate));
134 #elif defined(OS_WIN) 147 base::TimeDelta sleep_duration =
135 ::SuspendThread(thread_handle.platform_handle()); 148 base::TimeDelta::FromMicroseconds(quant_time_us) - run_duration;
149 Sleep(run_duration);
150 ::SuspendThread(throttled_thread_handle_.platform_handle());
151 Sleep(sleep_duration);
152 ::ResumeThread(throttled_thread_handle_.platform_handle());
153 #else
154 pthread_kill(throttled_thread_handle_.platform_handle(), SIGUSR2);
155 Sleep(base::TimeDelta::FromMicroseconds(quant_time_us));
136 #endif 156 #endif
137 } 157 }
138 158
139 // static
140 void CPUThrottlingThread::ResumeThread(
141 base::PlatformThreadHandle thread_handle) {
142 #if defined(USE_SIGNALS)
143 Release_Store(&suspended_, 0);
144 #elif defined(OS_WIN)
145 ::ResumeThread(thread_handle.platform_handle());
146 #endif
147 }
148
149 void CPUThrottlingThread::Start() { 159 void CPUThrottlingThread::Start() {
150 #ifdef USE_SIGNALS 160 #ifdef USE_SIGNALS
151 InstallSignalHandler(); 161 InstallSignalHandler();
152 #elif !defined(OS_WIN) 162 #elif !defined(OS_WIN)
153 LOG(ERROR) << "CPU throttling is not supported." 163 LOG(ERROR) << "CPU throttling is not supported."
154 #endif 164 #endif
155 if (!base::PlatformThread::Create(0, this, &throttling_thread_handle_)) { 165 if (!base::PlatformThread::Create(0, this, &throttling_thread_handle_)) {
156 LOG(ERROR) << "Failed to create throttling thread."; 166 LOG(ERROR) << "Failed to create throttling thread.";
157 } 167 }
158 } 168 }
(...skipping 10 matching lines...) Expand all
169 } 179 }
170 180
171 void CPUThrottlingThread::Stop() { 181 void CPUThrottlingThread::Stop() {
172 cancellation_flag_.Set(); 182 cancellation_flag_.Set();
173 base::PlatformThread::Join(throttling_thread_handle_); 183 base::PlatformThread::Join(throttling_thread_handle_);
174 #ifdef USE_SIGNALS 184 #ifdef USE_SIGNALS
175 RestoreSignalHandler(); 185 RestoreSignalHandler();
176 #endif 186 #endif
177 } 187 }
178 188
179 void CPUThrottlingThread::Throttle() {
180 const int quant_time_us = 200;
181 double rate = Acquire_Load(&throttling_rate_percent_) / 100.;
182 base::TimeDelta run_duration =
183 base::TimeDelta::FromMicroseconds(static_cast<int>(quant_time_us / rate));
184 base::TimeDelta sleep_duration =
185 base::TimeDelta::FromMicroseconds(quant_time_us) - run_duration;
186 Sleep(run_duration);
187 SuspendThread(throttled_thread_handle_);
188 Sleep(sleep_duration);
189 ResumeThread(throttled_thread_handle_);
190 }
191
192 DevToolsCPUThrottler::DevToolsCPUThrottler() {} 189 DevToolsCPUThrottler::DevToolsCPUThrottler() {}
193 190
194 DevToolsCPUThrottler::~DevToolsCPUThrottler() {} 191 DevToolsCPUThrottler::~DevToolsCPUThrottler() {}
195 192
196 void DevToolsCPUThrottler::SetThrottlingRate(double rate) { 193 void DevToolsCPUThrottler::SetThrottlingRate(double rate) {
197 if (rate <= 1) { 194 if (rate <= 1) {
198 if (throttling_thread_) { 195 if (throttling_thread_) {
199 throttling_thread_.reset(); 196 throttling_thread_.reset();
200 } 197 }
201 return; 198 return;
202 } 199 }
203 if (throttling_thread_) { 200 if (throttling_thread_) {
204 throttling_thread_->SetThrottlingRate(rate); 201 throttling_thread_->SetThrottlingRate(rate);
205 } else { 202 } else {
206 throttling_thread_.reset(new CPUThrottlingThread(rate)); 203 throttling_thread_.reset(new CPUThrottlingThread(rate));
207 } 204 }
208 } 205 }
209 206
210 } // namespace content 207 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698