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

Side by Side Diff: Source/core/workers/WorkerThreadTest.cpp

Issue 1130413003: Schedule garbage collection on worker threads using idle tasks (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix locking in test. Created 5 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 | Annotate | Revision Log
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 "config.h" 5 #include "config.h"
6 #include "core/workers/WorkerThread.h" 6 #include "core/workers/WorkerThread.h"
7 7
8 #include "core/inspector/ConsoleMessage.h" 8 #include "core/inspector/ConsoleMessage.h"
9 #include "core/workers/WorkerReportingProxy.h" 9 #include "core/workers/WorkerReportingProxy.h"
10 #include "core/workers/WorkerThreadStartupData.h" 10 #include "core/workers/WorkerThreadStartupData.h"
11 #include "platform/NotImplemented.h" 11 #include "platform/NotImplemented.h"
12 #include "public/platform/WebScheduler.h"
12 #include "public/platform/WebWaitableEvent.h" 13 #include "public/platform/WebWaitableEvent.h"
13 #include <gmock/gmock.h> 14 #include <gmock/gmock.h>
14 #include <gtest/gtest.h> 15 #include <gtest/gtest.h>
15 16
16 using testing::_; 17 using testing::_;
17 using testing::Invoke; 18 using testing::Invoke;
18 using testing::Return; 19 using testing::Return;
19 using testing::Mock; 20 using testing::Mock;
20 21
21 namespace blink { 22 namespace blink {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 } 91 }
91 92
92 ~WorkerThreadForTest() override { } 93 ~WorkerThreadForTest() override { }
93 94
94 // WorkerThread implementation: 95 // WorkerThread implementation:
95 WebThreadSupportingGC& backingThread() override 96 WebThreadSupportingGC& backingThread() override
96 { 97 {
97 return *m_thread; 98 return *m_thread;
98 } 99 }
99 100
101 MOCK_METHOD1(doIdleGc, bool(double deadlineSeconds));
102
100 PassRefPtrWillBeRawPtr<WorkerGlobalScope> createWorkerGlobalScope(PassOwnPtr <WorkerThreadStartupData> startupData) override 103 PassRefPtrWillBeRawPtr<WorkerGlobalScope> createWorkerGlobalScope(PassOwnPtr <WorkerThreadStartupData> startupData) override
101 { 104 {
102 return adoptRefWillBeNoop(new FakeWorkerGlobalScope(startupData->m_scrip tURL, startupData->m_userAgent, this, startupData->m_starterOrigin, startupData- >m_workerClients.release())); 105 return adoptRefWillBeNoop(new FakeWorkerGlobalScope(startupData->m_scrip tURL, startupData->m_userAgent, this, startupData->m_starterOrigin, startupData- >m_workerClients.release()));
103 } 106 }
104 107
105 private: 108 private:
106 OwnPtr<WebThreadSupportingGC> m_thread; 109 OwnPtr<WebThreadSupportingGC> m_thread;
107 }; 110 };
108 111
112 class WakeupTask : public WebThread::Task {
113 public:
114 WakeupTask() { }
115
116 ~WakeupTask() override { }
117
118 void run() override { }
119 };
120
121 class PostDelayedWakeupTask : public WebThread::Task {
122 public:
123 PostDelayedWakeupTask(WebScheduler* scheduler, long long delay) : m_schedule r(scheduler), m_delay(delay) { }
124
125 ~PostDelayedWakeupTask() override { }
126
127 void run() override
128 {
129 m_scheduler->postTimerTask(FROM_HERE, new WakeupTask(), m_delay);
130 }
131
132 WebScheduler* m_scheduler; // Not owned.
133 long long m_delay;
134 };
135
109 class SignalTask : public WebThread::Task { 136 class SignalTask : public WebThread::Task {
110 public: 137 public:
111 SignalTask(WebWaitableEvent* completionEvent) : m_completionEvent(completion Event) { } 138 SignalTask(WebWaitableEvent* completionEvent) : m_completionEvent(completion Event) { }
112 139
113 ~SignalTask() override { } 140 ~SignalTask() override { }
114 141
115 void run() override 142 void run() override
116 { 143 {
117 m_completionEvent->signal(); 144 m_completionEvent->signal();
118 } 145 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 181
155 void startAndWaitForInit() 182 void startAndWaitForInit()
156 { 183 {
157 OwnPtr<WebWaitableEvent> completionEvent = adoptPtr(Platform::current()- >createWaitableEvent()); 184 OwnPtr<WebWaitableEvent> completionEvent = adoptPtr(Platform::current()- >createWaitableEvent());
158 185
159 m_workerThread->start(); 186 m_workerThread->start();
160 m_workerThread->backingThread().postTask(FROM_HERE, new SignalTask(compl etionEvent.get())); 187 m_workerThread->backingThread().postTask(FROM_HERE, new SignalTask(compl etionEvent.get()));
161 completionEvent->wait(); 188 completionEvent->wait();
162 } 189 }
163 190
191 void postWakeUpTask(long long waitMs)
192 {
193 WebScheduler* scheduler = m_workerThread->backingThread().platformThread ().scheduler();
194
195 // The idle task will get posted on an after wake up queue, so we need a nother task
196 // posted at the right time to wake the system up. We don't know the ri ght delay here
197 // since the thread can take a variable length of time to be responsive, however this
198 // isn't a problem when posting a delayed task from within a task on the worker thread.
199 scheduler->postLoadingTask(FROM_HERE, new PostDelayedWakeupTask(schedule r, waitMs));
200 }
201
164 protected: 202 protected:
165 void ExpectWorkerLifetimeReportingCalls() 203 void ExpectWorkerLifetimeReportingCalls()
166 { 204 {
167 EXPECT_CALL(*m_mockWorkerReportingProxy, workerGlobalScopeStarted(_)).Ti mes(1); 205 EXPECT_CALL(*m_mockWorkerReportingProxy, workerGlobalScopeStarted(_)).Ti mes(1);
168 EXPECT_CALL(*m_mockWorkerReportingProxy, didEvaluateWorkerScript(true)). Times(1); 206 EXPECT_CALL(*m_mockWorkerReportingProxy, didEvaluateWorkerScript(true)). Times(1);
169 EXPECT_CALL(*m_mockWorkerReportingProxy, workerThreadTerminated()).Times (1); 207 EXPECT_CALL(*m_mockWorkerReportingProxy, workerThreadTerminated()).Times (1);
170 EXPECT_CALL(*m_mockWorkerReportingProxy, willDestroyWorkerGlobalScope()) .Times(1); 208 EXPECT_CALL(*m_mockWorkerReportingProxy, willDestroyWorkerGlobalScope()) .Times(1);
171 } 209 }
172 210
173 RefPtr<SecurityOrigin> m_securityOrigin; 211 RefPtr<SecurityOrigin> m_securityOrigin;
174 OwnPtr<MockWorkerLoaderProxyProvider> m_mockWorkerLoaderProxyProvider; 212 OwnPtr<MockWorkerLoaderProxyProvider> m_mockWorkerLoaderProxyProvider;
175 OwnPtr<MockWorkerReportingProxy> m_mockWorkerReportingProxy; 213 OwnPtr<MockWorkerReportingProxy> m_mockWorkerReportingProxy;
176 RefPtr<WorkerThreadForTest> m_workerThread; 214 RefPtr<WorkerThreadForTest> m_workerThread;
177 }; 215 };
178 216
179 TEST_F(WorkerThreadTest, StartAndStop) 217 TEST_F(WorkerThreadTest, StartAndStop)
180 { 218 {
181 startAndWaitForInit(); 219 startAndWaitForInit();
182 m_workerThread->terminateAndWait(); 220 m_workerThread->terminateAndWait();
183 } 221 }
184 222
223 TEST_F(WorkerThreadTest, GcOccursWhileIdle)
224 {
225 OwnPtr<WebWaitableEvent> gcDone = adoptPtr(Platform::current()->createWaitab leEvent());
226
227 ON_CALL(*m_workerThread, doIdleGc(_)).WillByDefault(Invoke(
228 [&gcDone](double)
229 {
230 gcDone->signal();
231 return false;
232 }));
233
234 EXPECT_CALL(*m_workerThread, doIdleGc(_)).Times(1);
235
236 startAndWaitForInit();
237 postWakeUpTask(310ul); // 10ms after the quiescent period ends.
238
239 gcDone->wait();
240 m_workerThread->terminateAndWait();
241 };
242
243 class RepeatingTask : public WebThread::Task {
244 public:
245 RepeatingTask(WebScheduler* scheduler, WebWaitableEvent* completion)
246 : RepeatingTask(scheduler, completion, 0) { }
247
248 ~RepeatingTask() override { }
249
250 void run() override
251 {
252 m_taskCount++;
253 if (m_taskCount == 10)
254 m_completion->signal();
255
256 m_scheduler->postTimerTask(
257 FROM_HERE, new RepeatingTask(m_scheduler, m_completion, m_taskCount) , 50ul);
258 m_scheduler->postLoadingTask(FROM_HERE, new WakeupTask());
259
260 }
261
262 private:
263 RepeatingTask(WebScheduler* scheduler, WebWaitableEvent* completion, int tas kCount)
264 : m_scheduler(scheduler)
265 , m_completion(completion)
266 , m_taskCount(taskCount)
267 { }
268
269 WebScheduler* m_scheduler; // Not owned.
270 WebWaitableEvent* m_completion;
271 int m_taskCount;
272 };
273
274 TEST_F(WorkerThreadTest, GcDoesNotOccurIfGapBetweenDelayedTasksIsTooSmall)
275 {
276 OwnPtr<WebWaitableEvent> completion = adoptPtr(Platform::current()->createWa itableEvent());
277
278 EXPECT_CALL(*m_workerThread, doIdleGc(_)).Times(0);
279
280 startAndWaitForInit();
281
282 WebScheduler* scheduler = m_workerThread->backingThread().platformThread().s cheduler();
283
284 // Post a repeating task that should prevent any GC from happening.
285 scheduler->postLoadingTask(FROM_HERE, new RepeatingTask(scheduler, completio n.get()));
286
287 completion->wait();
288
289 // Make sure doIdleGc has not been called by this stage.
290 Mock::VerifyAndClearExpectations(m_workerThread.get());
291
292 m_workerThread->terminateAndWait();
293 }
294
295 TEST_F(WorkerThreadTest, LongGcDeadline_NoFutureTasks)
296 {
297 OwnPtr<WebWaitableEvent> gcDone = adoptPtr(Platform::current()->createWaitab leEvent());
298 double deadlineLength = 0;
299
300 ON_CALL(*m_workerThread, doIdleGc(_)).WillByDefault(Invoke(
301 [&gcDone, &deadlineLength](double deadline)
302 {
303 deadlineLength = deadline - Platform::current()->monotonicallyIncrea singTime();
304 gcDone->signal();
305 return false;
306 }));
307
308 EXPECT_CALL(*m_workerThread, doIdleGc(_)).Times(1);
309
310 startAndWaitForInit();
311 postWakeUpTask(310ul);
312
313 gcDone->wait();
314
315 // The deadline should be close to 1s in duration if there are no tasks that need to run soon.
316 EXPECT_GT(deadlineLength, 0.9);
317
318 m_workerThread->terminateAndWait();
319 }
320
321 TEST_F(WorkerThreadTest, LongGcDeadline_NextTaskAfterIdlePeriod)
322 {
323 OwnPtr<WebWaitableEvent> gcDone = adoptPtr(Platform::current()->createWaitab leEvent());
324 double deadlineLength = 0;
325
326 ON_CALL(*m_workerThread, doIdleGc(_)).WillByDefault(Invoke(
327 [&gcDone, &deadlineLength](double deadline)
328 {
329 deadlineLength = deadline - Platform::current()->monotonicallyIncrea singTime();
330 gcDone->signal();
331 return false;
332 }));
333
334 EXPECT_CALL(*m_workerThread, doIdleGc(_)).Times(1);
335
336 startAndWaitForInit();
337 postWakeUpTask(310ul);
338 postWakeUpTask(675ul); // Task that runs shortly after the 50ms idle period ends.
339
340 gcDone->wait();
341
342 // The worker thread calls canExceedIdleDeadlineIfRequired which only consid ers if
343 // there are any delayed tasks scheduled for the current long idle period. Since the
344 // next task is in the following idle period, a long gc deadline is allowed.
345 EXPECT_GT(deadlineLength, 0.9);
346
347 m_workerThread->terminateAndWait();
348 }
349
350 TEST_F(WorkerThreadTest, ShortGcDeadline)
351 {
352 OwnPtr<WebWaitableEvent> gcDone = adoptPtr(Platform::current()->createWaitab leEvent());
353 double deadlineLength = 0;
354
355 ON_CALL(*m_workerThread, doIdleGc(_)).WillByDefault(Invoke(
356 [&gcDone, &deadlineLength](double deadline)
357 {
358 deadlineLength = deadline - Platform::current()->monotonicallyIncrea singTime();
359 gcDone->signal();
360 return false;
361 }));
362
363 EXPECT_CALL(*m_workerThread, doIdleGc(_)).Times(1);
364
365 startAndWaitForInit();
366 postWakeUpTask(310ul);
367 postWakeUpTask(625ul); // Task that runs during the idle period.
368
369 gcDone->wait();
370
371 // The deadline should be < 50ms if there's a task that needs to run during the idle period.
372 EXPECT_LT(deadlineLength, 0.025);
373
374 m_workerThread->terminateAndWait();
375 }
376
185 } // namespace blink 377 } // namespace blink
OLDNEW
« Source/core/workers/WorkerThread.cpp ('K') | « Source/core/workers/WorkerThread.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698