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

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, 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
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> {
darin (slow to review) 2013/05/11 06:02:19 should you indicate a thread on which this object
shatch 2013/05/13 17:47:47 Done.
39 public:
40 WorkerPrioritySetter();
jam 2013/05/28 14:28:30 nit: since this class is all in the cc file, why s
shatch 2013/05/28 17:52:13 I guess it was the opposite for me, find it easier
jam 2013/05/28 17:56:18 ok, up to you since this is personal style and not
41
42 // Invoked by WorkerServiceImpl when a worker process is created.
43 void NotifyWorkerProcessCreated();
44
45 private:
46 friend class base::RefCountedThreadSafe<WorkerPrioritySetter>;
47 virtual ~WorkerPrioritySetter();
48
49 // Posts a task to perform a worker priority update.
50 void PostTaskToGatherAndUpdateWorkerPriorities();
51
52 // Gathers up a list of the visible tabs and then updates priorities for
53 // all the shared workers.
54 void GatherVisibleIDsAndUpdateWorkerPriorities();
55
56 // Registers as an observer to receive notifications about
57 // widgets being shown.
58 void RegisterObserver();
59
60 // Sets priorities for shared workers given a set of visible tabs (as a
61 // std::set of std::pair<render_process, render_view> ids.
62 void UpdateWorkerPrioritiesFromVisibleSet(
63 const std::set<std::pair<int, int> >* visible);
64
65 // Called to refresh worker priorities when focus changes between tabs.
66 void OnRenderWidgetVisibilityChanged(std::pair<int, int>);
67
68 // NotificationObserver implementation.
69 virtual void Observe(int type,
70 const NotificationSource& source,
71 const NotificationDetails& details) OVERRIDE;
72
73 NotificationRegistrar registrar_;
74 };
75
76 WorkerPrioritySetter::WorkerPrioritySetter() {
77 BrowserThread::PostTask(
78 BrowserThread::UI, FROM_HERE,
79 base::Bind(&WorkerPrioritySetter::RegisterObserver, this));
80 }
81
82 WorkerPrioritySetter::~WorkerPrioritySetter() {
83 }
84
85 void WorkerPrioritySetter::NotifyWorkerProcessCreated() {
86 PostTaskToGatherAndUpdateWorkerPriorities();
87 }
88
89 void WorkerPrioritySetter::PostTaskToGatherAndUpdateWorkerPriorities() {
90 BrowserThread::PostTask(
91 BrowserThread::UI, FROM_HERE,
92 base::Bind(
93 &WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities,
94 this));
95 }
96
97 void WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities() {
98 std::set<std::pair<int, int> >* visible_renderer_ids =
99 new std::set<std::pair<int, int> >();
100
101 // Gather up all the visible renderer process/view pairs
102 for (RenderProcessHost::iterator it =
103 RenderProcessHost::AllHostsIterator();
104 !it.IsAtEnd(); it.Advance()) {
105 RenderProcessHost* render_process_host = it.GetCurrentValue();
106 if (render_process_host->VisibleWidgetCount()) {
107 for (RenderProcessHost::RenderWidgetHostsIterator rit =
108 render_process_host->GetRenderWidgetHostsIterator(); !rit.IsAtEnd();
109 rit.Advance()) {
110 RenderWidgetHost* render_widget =
111 render_process_host->GetRenderWidgetHostByID(rit.GetCurrentKey());
112 if (render_widget) {
113 RenderWidgetHostView* render_view = render_widget->GetView();
114 if (render_view && render_view->IsShowing()) {
115 visible_renderer_ids->insert(
116 std::pair<int, int>(render_process_host->GetID(),
117 render_widget->GetRoutingID()));
118 }
119 }
120 }
121 }
122 }
123
124 BrowserThread::PostTask(
125 BrowserThread::IO, FROM_HERE,
126 base::Bind(&WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet,
127 this, base::Owned(visible_renderer_ids)));
128 }
129
130 void WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet(
131 const std::set<std::pair<int, int> >* visible_renderer_ids) {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
darin (slow to review) 2013/05/11 06:02:19 nit: How about adding more DCHECKs like these to o
shatch 2013/05/13 17:47:47 Done.
133
134 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
135 if (!iter->process_launched())
136 continue;
137 bool throttle = true;
138
139 for (WorkerProcessHost::Instances::const_iterator instance =
140 iter->instances().begin(); instance != iter->instances().end();
141 ++instance) {
142
143 // This code assumes one worker per process
144 WorkerProcessHost::Instances::const_iterator first_instance =
145 iter->instances().begin();
146 if (first_instance == iter->instances().end())
147 continue;
148
149 WorkerDocumentSet::DocumentInfoSet::const_iterator info =
150 first_instance->worker_document_set()->documents().begin();
151
152 for (; info != first_instance->worker_document_set()->documents().end();
153 ++info) {
154 std::pair<int, int> id(
155 info->render_process_id(), info->render_view_id());
156 if (visible_renderer_ids->find(id) != visible_renderer_ids->end()) {
157 throttle = false;
158 break;
159 }
160 }
161
162 if (!throttle ) {
163 break;
164 }
165 }
166
167 iter->SetBackgrounded(throttle);
168 }
169 }
170
171 void WorkerPrioritySetter::OnRenderWidgetVisibilityChanged(
172 std::pair<int, int> id) {
173 std::set<std::pair<int, int> > visible_renderer_ids;
174
175 visible_renderer_ids.insert(id);
176
177 UpdateWorkerPrioritiesFromVisibleSet(&visible_renderer_ids);
178 }
179
180 void WorkerPrioritySetter::RegisterObserver() {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182 registrar_.Add(this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
183 NotificationService::AllBrowserContextsAndSources());
184 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
185 NotificationService::AllBrowserContextsAndSources());
186 }
187
188 void WorkerPrioritySetter::Observe(int type,
189 const NotificationSource& source, const NotificationDetails& details) {
190 if (type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
191 bool visible = *Details<bool>(details).ptr();
192
193 if (visible) {
194 int render_widget_id =
195 Source<RenderWidgetHost>(source).ptr()->GetRoutingID();
196 int render_process_pid =
197 Source<RenderWidgetHost>(source).ptr()->GetProcess()->GetID();
198
199 BrowserThread::PostTask(
200 BrowserThread::IO, FROM_HERE,
201 base::Bind(&WorkerPrioritySetter::OnRenderWidgetVisibilityChanged,
202 this, std::pair<int, int>(render_process_pid, render_widget_id)));
203 }
204 }
205 else if (type == NOTIFICATION_RENDERER_PROCESS_CREATED) {
206 PostTaskToGatherAndUpdateWorkerPriorities();
207 }
208 }
209
28 WorkerService* WorkerService::GetInstance() { 210 WorkerService* WorkerService::GetInstance() {
29 return WorkerServiceImpl::GetInstance(); 211 return WorkerServiceImpl::GetInstance();
30 } 212 }
31 213
32 WorkerServiceImpl* WorkerServiceImpl::GetInstance() { 214 WorkerServiceImpl* WorkerServiceImpl::GetInstance() {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
34 return Singleton<WorkerServiceImpl>::get(); 216 return Singleton<WorkerServiceImpl>::get();
35 } 217 }
36 218
37 WorkerServiceImpl::WorkerServiceImpl() : next_worker_route_id_(0) { 219 WorkerServiceImpl::WorkerServiceImpl()
220 : priority_setter_(new WorkerPrioritySetter()),
221 next_worker_route_id_(0) {
38 } 222 }
39 223
40 WorkerServiceImpl::~WorkerServiceImpl() { 224 WorkerServiceImpl::~WorkerServiceImpl() {
41 // The observers in observers_ can't be used here because they might be 225 // The observers in observers_ can't be used here because they might be
42 // gone already. 226 // gone already.
43 } 227 }
44 228
45 void WorkerServiceImpl::OnWorkerMessageFilterClosing( 229 void WorkerServiceImpl::OnWorkerMessageFilterClosing(
46 WorkerMessageFilter* filter) { 230 WorkerMessageFilter* filter) {
47 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { 231 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 634
451 void WorkerServiceImpl::NotifyWorkerDestroyed( 635 void WorkerServiceImpl::NotifyWorkerDestroyed(
452 WorkerProcessHost* process, 636 WorkerProcessHost* process,
453 int worker_route_id) { 637 int worker_route_id) {
454 WorkerDevToolsManager::GetInstance()->WorkerDestroyed( 638 WorkerDevToolsManager::GetInstance()->WorkerDestroyed(
455 process, worker_route_id); 639 process, worker_route_id);
456 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, 640 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_,
457 WorkerDestroyed(process->GetData().id, worker_route_id)); 641 WorkerDestroyed(process->GetData().id, worker_route_id));
458 } 642 }
459 643
644 void WorkerServiceImpl::NotifyWorkerProcessCreated() {
645 priority_setter_->NotifyWorkerProcessCreated();
646 }
647
460 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( 648 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance(
461 const GURL& url, 649 const GURL& url,
462 const string16& name, 650 const string16& name,
463 const WorkerStoragePartition& partition, 651 const WorkerStoragePartition& partition,
464 ResourceContext* resource_context) { 652 ResourceContext* resource_context) {
465 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { 653 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
466 for (WorkerProcessHost::Instances::iterator instance_iter = 654 for (WorkerProcessHost::Instances::iterator instance_iter =
467 iter->mutable_instances().begin(); 655 iter->mutable_instances().begin();
468 instance_iter != iter->mutable_instances().end(); 656 instance_iter != iter->mutable_instances().end();
469 ++instance_iter) { 657 ++instance_iter) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 return instance; 708 return instance;
521 709
522 // No existing pending worker - create a new one. 710 // No existing pending worker - create a new one.
523 WorkerProcessHost::WorkerInstance pending( 711 WorkerProcessHost::WorkerInstance pending(
524 url, true, name, resource_context, partition); 712 url, true, name, resource_context, partition);
525 pending_shared_workers_.push_back(pending); 713 pending_shared_workers_.push_back(pending);
526 return &pending_shared_workers_.back(); 714 return &pending_shared_workers_.back();
527 } 715 }
528 716
529 } // namespace content 717 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698