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

Side by Side Diff: content/browser/worker_host/worker_service_impl.cc

Issue 14137016: Lower the priority of shared workers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changes from review. Created 7 years, 6 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 | « content/browser/worker_host/worker_service_impl.h ('k') | 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 (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 "content/browser/worker_host/worker_service_impl.h" 5 #include "content/browser/worker_host/worker_service_impl.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/threading/thread.h" 11 #include "base/threading/thread.h"
12 #include "content/browser/devtools/worker_devtools_manager.h" 12 #include "content/browser/devtools/worker_devtools_manager.h"
13 #include "content/browser/renderer_host/render_widget_host_impl.h"
13 #include "content/browser/worker_host/worker_message_filter.h" 14 #include "content/browser/worker_host/worker_message_filter.h"
14 #include "content/browser/worker_host/worker_process_host.h" 15 #include "content/browser/worker_host/worker_process_host.h"
15 #include "content/common/view_messages.h" 16 #include "content/common/view_messages.h"
16 #include "content/common/worker_messages.h" 17 #include "content/common/worker_messages.h"
17 #include "content/public/browser/child_process_data.h" 18 #include "content/public/browser/child_process_data.h"
19 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/notification_types.h"
21 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/render_view_host.h"
23 #include "content/public/browser/render_widget_host.h"
24 #include "content/public/browser/render_widget_host_view.h"
18 #include "content/public/browser/resource_context.h" 25 #include "content/public/browser/resource_context.h"
26 #include "content/public/browser/web_contents.h"
19 #include "content/public/browser/worker_service_observer.h" 27 #include "content/public/browser/worker_service_observer.h"
20 #include "content/public/common/content_switches.h" 28 #include "content/public/common/content_switches.h"
21 #include "content/public/common/process_type.h" 29 #include "content/public/common/process_type.h"
22 30
23 namespace content { 31 namespace content {
24 32
25 const int WorkerServiceImpl::kMaxWorkersWhenSeparate = 64; 33 const int WorkerServiceImpl::kMaxWorkersWhenSeparate = 64;
26 const int WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate = 16; 34 const int WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate = 16;
27 35
36 class WorkerPrioritySetter
37 : public NotificationObserver,
38 public base::RefCountedThreadSafe<WorkerPrioritySetter,
39 BrowserThread::DeleteOnUIThread> {
40 public:
41 WorkerPrioritySetter();
42
43 // Posts a task to the UI thread to register to receive notifications.
44 void Initialize();
45
46 // Invoked by WorkerServiceImpl when a worker process is created.
47 void NotifyWorkerProcessCreated();
48
49 private:
50 friend class base::RefCountedThreadSafe<WorkerPrioritySetter>;
51 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
52 friend class base::DeleteHelper<WorkerPrioritySetter>;
53 virtual ~WorkerPrioritySetter();
54
55 // Posts a task to perform a worker priority update.
56 void PostTaskToGatherAndUpdateWorkerPriorities();
57
58 // Gathers up a list of the visible tabs and then updates priorities for
59 // all the shared workers.
60 void GatherVisibleIDsAndUpdateWorkerPriorities();
61
62 // Registers as an observer to receive notifications about
63 // widgets being shown.
64 void RegisterObserver();
65
66 // Sets priorities for shared workers given a set of visible tabs (as a
67 // std::set of std::pair<render_process, render_view> ids.
68 void UpdateWorkerPrioritiesFromVisibleSet(
69 const std::set<std::pair<int, int> >* visible);
70
71 // Called to refresh worker priorities when focus changes between tabs.
72 void OnRenderWidgetVisibilityChanged(std::pair<int, int>);
73
74 // NotificationObserver implementation.
75 virtual void Observe(int type,
76 const NotificationSource& source,
77 const NotificationDetails& details) OVERRIDE;
78
79 NotificationRegistrar registrar_;
80 };
81
82 WorkerPrioritySetter::WorkerPrioritySetter() {
83 }
84
85 WorkerPrioritySetter::~WorkerPrioritySetter() {
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
87 }
88
89 void WorkerPrioritySetter::Initialize() {
90 BrowserThread::PostTask(
91 BrowserThread::UI, FROM_HERE,
92 base::Bind(&WorkerPrioritySetter::RegisterObserver, this));
93 }
94
95 void WorkerPrioritySetter::NotifyWorkerProcessCreated() {
96 PostTaskToGatherAndUpdateWorkerPriorities();
97 }
98
99 void WorkerPrioritySetter::PostTaskToGatherAndUpdateWorkerPriorities() {
100 BrowserThread::PostTask(
101 BrowserThread::UI, FROM_HERE,
102 base::Bind(
103 &WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities,
104 this));
105 }
106
107 void WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities() {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109 std::set<std::pair<int, int> >* visible_renderer_ids =
110 new std::set<std::pair<int, int> >();
111
112 // Gather up all the visible renderer process/view pairs
113 for (RenderProcessHost::iterator it =
114 RenderProcessHost::AllHostsIterator();
115 !it.IsAtEnd(); it.Advance()) {
116 RenderProcessHost* render_process_host = it.GetCurrentValue();
117 if (render_process_host->VisibleWidgetCount()) {
118 for (RenderProcessHost::RenderWidgetHostsIterator rit =
119 render_process_host->GetRenderWidgetHostsIterator(); !rit.IsAtEnd();
120 rit.Advance()) {
121 RenderWidgetHost* render_widget =
122 render_process_host->GetRenderWidgetHostByID(rit.GetCurrentKey());
123 if (render_widget) {
124 RenderWidgetHostView* render_view = render_widget->GetView();
125 if (render_view && render_view->IsShowing()) {
126 visible_renderer_ids->insert(
127 std::pair<int, int>(render_process_host->GetID(),
128 render_widget->GetRoutingID()));
129 }
130 }
131 }
132 }
133 }
134
135 BrowserThread::PostTask(
136 BrowserThread::IO, FROM_HERE,
137 base::Bind(&WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet,
138 this, base::Owned(visible_renderer_ids)));
139 }
140
141 void WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet(
142 const std::set<std::pair<int, int> >* visible_renderer_ids) {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
144
145 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
146 if (!iter->process_launched())
147 continue;
148 bool throttle = true;
149
150 for (WorkerProcessHost::Instances::const_iterator instance =
151 iter->instances().begin(); instance != iter->instances().end();
152 ++instance) {
153
154 // This code assumes one worker per process
155 WorkerProcessHost::Instances::const_iterator first_instance =
156 iter->instances().begin();
157 if (first_instance == iter->instances().end())
158 continue;
159
160 WorkerDocumentSet::DocumentInfoSet::const_iterator info =
161 first_instance->worker_document_set()->documents().begin();
162
163 for (; info != first_instance->worker_document_set()->documents().end();
164 ++info) {
165 std::pair<int, int> id(
166 info->render_process_id(), info->render_view_id());
167 if (visible_renderer_ids->find(id) != visible_renderer_ids->end()) {
168 throttle = false;
169 break;
170 }
171 }
172
173 if (!throttle ) {
174 break;
175 }
176 }
177
178 iter->SetBackgrounded(throttle);
179 }
180 }
181
182 void WorkerPrioritySetter::OnRenderWidgetVisibilityChanged(
183 std::pair<int, int> id) {
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
185 std::set<std::pair<int, int> > visible_renderer_ids;
186
187 visible_renderer_ids.insert(id);
188
189 UpdateWorkerPrioritiesFromVisibleSet(&visible_renderer_ids);
190 }
191
192 void WorkerPrioritySetter::RegisterObserver() {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194 registrar_.Add(this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
195 NotificationService::AllBrowserContextsAndSources());
196 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
197 NotificationService::AllBrowserContextsAndSources());
198 }
199
200 void WorkerPrioritySetter::Observe(int type,
201 const NotificationSource& source, const NotificationDetails& details) {
202 if (type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
203 bool visible = *Details<bool>(details).ptr();
204
205 if (visible) {
206 int render_widget_id =
207 Source<RenderWidgetHost>(source).ptr()->GetRoutingID();
208 int render_process_pid =
209 Source<RenderWidgetHost>(source).ptr()->GetProcess()->GetID();
210
211 BrowserThread::PostTask(
212 BrowserThread::IO, FROM_HERE,
213 base::Bind(&WorkerPrioritySetter::OnRenderWidgetVisibilityChanged,
214 this, std::pair<int, int>(render_process_pid, render_widget_id)));
215 }
216 }
217 else if (type == NOTIFICATION_RENDERER_PROCESS_CREATED) {
218 PostTaskToGatherAndUpdateWorkerPriorities();
219 }
220 }
221
28 WorkerService* WorkerService::GetInstance() { 222 WorkerService* WorkerService::GetInstance() {
29 return WorkerServiceImpl::GetInstance(); 223 return WorkerServiceImpl::GetInstance();
30 } 224 }
31 225
32 WorkerServiceImpl* WorkerServiceImpl::GetInstance() { 226 WorkerServiceImpl* WorkerServiceImpl::GetInstance() {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
34 return Singleton<WorkerServiceImpl>::get(); 228 return Singleton<WorkerServiceImpl>::get();
35 } 229 }
36 230
37 WorkerServiceImpl::WorkerServiceImpl() : next_worker_route_id_(0) { 231 WorkerServiceImpl::WorkerServiceImpl()
232 : priority_setter_(new WorkerPrioritySetter()),
233 next_worker_route_id_(0) {
234 priority_setter_->Initialize();
38 } 235 }
39 236
40 WorkerServiceImpl::~WorkerServiceImpl() { 237 WorkerServiceImpl::~WorkerServiceImpl() {
41 // The observers in observers_ can't be used here because they might be 238 // The observers in observers_ can't be used here because they might be
42 // gone already. 239 // gone already.
43 } 240 }
44 241
242 void WorkerServiceImpl::PerformTeardownForTesting() {
243 priority_setter_ = NULL;
244 }
245
45 void WorkerServiceImpl::OnWorkerMessageFilterClosing( 246 void WorkerServiceImpl::OnWorkerMessageFilterClosing(
46 WorkerMessageFilter* filter) { 247 WorkerMessageFilter* filter) {
47 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { 248 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
48 iter->FilterShutdown(filter); 249 iter->FilterShutdown(filter);
49 } 250 }
50 251
51 // See if that process had any queued workers. 252 // See if that process had any queued workers.
52 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); 253 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin();
53 i != queued_workers_.end();) { 254 i != queued_workers_.end();) {
54 i->RemoveFilters(filter); 255 i->RemoveFilters(filter);
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 651
451 void WorkerServiceImpl::NotifyWorkerDestroyed( 652 void WorkerServiceImpl::NotifyWorkerDestroyed(
452 WorkerProcessHost* process, 653 WorkerProcessHost* process,
453 int worker_route_id) { 654 int worker_route_id) {
454 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( 655 WorkerDevToolsManager::GetInstance()->WorkerDestroyed(
455 process, worker_route_id); 656 process, worker_route_id);
456 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, 657 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_,
457 WorkerDestroyed(process->GetData().id, worker_route_id)); 658 WorkerDestroyed(process->GetData().id, worker_route_id));
458 } 659 }
459 660
661 void WorkerServiceImpl::NotifyWorkerProcessCreated() {
662 priority_setter_->NotifyWorkerProcessCreated();
663 }
664
460 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( 665 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance(
461 const GURL& url, 666 const GURL& url,
462 const string16& name, 667 const string16& name,
463 const WorkerStoragePartition& partition, 668 const WorkerStoragePartition& partition,
464 ResourceContext* resource_context) { 669 ResourceContext* resource_context) {
465 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { 670 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
466 for (WorkerProcessHost::Instances::iterator instance_iter = 671 for (WorkerProcessHost::Instances::iterator instance_iter =
467 iter->mutable_instances().begin(); 672 iter->mutable_instances().begin();
468 instance_iter != iter->mutable_instances().end(); 673 instance_iter != iter->mutable_instances().end();
469 ++instance_iter) { 674 ++instance_iter) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 return instance; 725 return instance;
521 726
522 // No existing pending worker - create a new one. 727 // No existing pending worker - create a new one.
523 WorkerProcessHost::WorkerInstance pending( 728 WorkerProcessHost::WorkerInstance pending(
524 url, true, name, resource_context, partition); 729 url, true, name, resource_context, partition);
525 pending_shared_workers_.push_back(pending); 730 pending_shared_workers_.push_back(pending);
526 return &pending_shared_workers_.back(); 731 return &pending_shared_workers_.back();
527 } 732 }
528 733
529 } // namespace content 734 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/worker_host/worker_service_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698