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

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

Issue 1130413003: Schedule garbage collection on worker threads using idle tasks (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebased. 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
« no previous file with comments | « Source/core/workers/WorkerThread.h ('k') | Source/core/workers/WorkerThreadTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 28 matching lines...) Expand all
39 #include "core/workers/WorkerReportingProxy.h" 39 #include "core/workers/WorkerReportingProxy.h"
40 #include "core/workers/WorkerThreadStartupData.h" 40 #include "core/workers/WorkerThreadStartupData.h"
41 #include "platform/PlatformThreadData.h" 41 #include "platform/PlatformThreadData.h"
42 #include "platform/Task.h" 42 #include "platform/Task.h"
43 #include "platform/ThreadSafeFunctional.h" 43 #include "platform/ThreadSafeFunctional.h"
44 #include "platform/ThreadTimers.h" 44 #include "platform/ThreadTimers.h"
45 #include "platform/heap/SafePoint.h" 45 #include "platform/heap/SafePoint.h"
46 #include "platform/heap/ThreadState.h" 46 #include "platform/heap/ThreadState.h"
47 #include "platform/weborigin/KURL.h" 47 #include "platform/weborigin/KURL.h"
48 #include "public/platform/Platform.h" 48 #include "public/platform/Platform.h"
49 #include "public/platform/WebScheduler.h"
49 #include "public/platform/WebThread.h" 50 #include "public/platform/WebThread.h"
50 #include "public/platform/WebWaitableEvent.h" 51 #include "public/platform/WebWaitableEvent.h"
51 #include "wtf/Noncopyable.h" 52 #include "wtf/Noncopyable.h"
52 #include "wtf/WeakPtr.h" 53 #include "wtf/WeakPtr.h"
53 #include "wtf/text/WTFString.h" 54 #include "wtf/text/WTFString.h"
54 55
55 namespace blink { 56 namespace blink {
56 57
57 namespace { 58 namespace {
58 const int64_t kShortIdleHandlerDelayMs = 1000; 59 const double kLongIdlePeriodSecs = 1.0;
59 const int64_t kLongIdleHandlerDelayMs = 10*1000;
60 60
61 } // namespace 61 } // namespace
62 62
63 class WorkerMicrotaskRunner : public WebThread::TaskObserver { 63 class WorkerMicrotaskRunner : public WebThread::TaskObserver {
64 public: 64 public:
65 explicit WorkerMicrotaskRunner(WorkerThread* workerThread) 65 explicit WorkerMicrotaskRunner(WorkerThread* workerThread)
66 : m_workerThread(workerThread) 66 : m_workerThread(workerThread)
67 { 67 {
68 } 68 }
69 69
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } 265 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { }
266 266
267 WorkerThread* m_thread; 267 WorkerThread* m_thread;
268 }; 268 };
269 269
270 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> star tupData) 270 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> star tupData)
271 : m_started(false) 271 : m_started(false)
272 , m_terminated(false) 272 , m_terminated(false)
273 , m_workerLoaderProxy(workerLoaderProxy) 273 , m_workerLoaderProxy(workerLoaderProxy)
274 , m_workerReportingProxy(workerReportingProxy) 274 , m_workerReportingProxy(workerReportingProxy)
275 , m_webScheduler(nullptr)
275 , m_startupData(startupData) 276 , m_startupData(startupData)
276 , m_isolate(nullptr) 277 , m_isolate(nullptr)
277 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent())) 278 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent()))
278 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent())) 279 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent()))
279 { 280 {
280 MutexLocker lock(threadSetMutex()); 281 MutexLocker lock(threadSetMutex());
281 workerThreads().add(this); 282 workerThreads().add(this);
282 } 283 }
283 284
284 WorkerThread::~WorkerThread() 285 WorkerThread::~WorkerThread()
(...skipping 27 matching lines...) Expand all
312 } 313 }
313 314
314 void WorkerThread::initialize() 315 void WorkerThread::initialize()
315 { 316 {
316 KURL scriptURL = m_startupData->m_scriptURL; 317 KURL scriptURL = m_startupData->m_scriptURL;
317 String sourceCode = m_startupData->m_sourceCode; 318 String sourceCode = m_startupData->m_sourceCode;
318 WorkerThreadStartMode startMode = m_startupData->m_startMode; 319 WorkerThreadStartMode startMode = m_startupData->m_startMode;
319 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas e(); 320 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas e();
320 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; 321 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions;
321 322
323 m_webScheduler = backingThread().platformThread().scheduler();
322 { 324 {
323 MutexLocker lock(m_threadStateMutex); 325 MutexLocker lock(m_threadStateMutex);
324 326
325 // The worker was terminated before the thread had a chance to run. 327 // The worker was terminated before the thread had a chance to run.
326 if (m_terminated) { 328 if (m_terminated) {
327 // Notify the proxy that the WorkerGlobalScope has been disposed of. 329 // Notify the proxy that the WorkerGlobalScope has been disposed of.
328 // This can free this thread object, hence it must not be touched af terwards. 330 // This can free this thread object, hence it must not be touched af terwards.
329 m_workerReportingProxy.workerThreadTerminated(); 331 m_workerReportingProxy.workerThreadTerminated();
330 return; 332 return;
331 } 333 }
(...skipping 21 matching lines...) Expand all
353 if (startMode == PauseWorkerGlobalScopeOnStart) 355 if (startMode == PauseWorkerGlobalScopeOnStart)
354 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); 356 m_workerGlobalScope->workerInspectorController()->pauseOnStart();
355 357
356 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip tCachedMetadataHandler(scriptURL, cachedMetaData.get())); 358 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip tCachedMetadataHandler(scriptURL, cachedMetaData.get()));
357 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul lptr, handler.get(), v8CacheOptions); 359 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul lptr, handler.get(), v8CacheOptions);
358 m_workerGlobalScope->didEvaluateWorkerScript(); 360 m_workerGlobalScope->didEvaluateWorkerScript();
359 m_workerReportingProxy.didEvaluateWorkerScript(success); 361 m_workerReportingProxy.didEvaluateWorkerScript(success);
360 362
361 postInitialize(); 363 postInitialize();
362 364
363 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs); 365 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, WTF::bind<double>(&Worker Thread::performIdleWork, this));
364 } 366 }
365 367
366 void WorkerThread::shutdown() 368 void WorkerThread::shutdown()
367 { 369 {
368 MutexLocker lock(m_threadStateMutex); 370 MutexLocker lock(m_threadStateMutex);
369 ASSERT(isCurrentThread()); 371 ASSERT(isCurrentThread());
370 372
371 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); 373 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr);
372 workerGlobalScope()->dispose(); 374 workerGlobalScope()->dispose();
373 willDestroyIsolate(); 375 willDestroyIsolate();
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 474
473 for (WorkerThread* thread : threads) 475 for (WorkerThread* thread : threads)
474 thread->terminationEvent()->wait(); 476 thread->terminationEvent()->wait();
475 } 477 }
476 478
477 bool WorkerThread::isCurrentThread() 479 bool WorkerThread::isCurrentThread()
478 { 480 {
479 return m_started && backingThread().isCurrentThread(); 481 return m_started && backingThread().isCurrentThread();
480 } 482 }
481 483
482 void WorkerThread::idleHandler() 484 void WorkerThread::performIdleWork(double deadlineSeconds)
483 { 485 {
484 ASSERT(m_workerGlobalScope.get()); 486 double gcDeadlineSeconds = deadlineSeconds;
485 int64_t delay = kLongIdleHandlerDelayMs;
486 487
487 // Do a script engine idle notification if the next event is distant enough. 488 // The V8 GC does some GC steps (e.g. compaction) only when the idle notific ation is ~1s.
488 const double kMinIdleTimespan = 0.3; 489 // TODO(rmcilroy): Refactor so extending the deadline like this this isn't n eeded.
489 const double nextFireTime = PlatformThreadData::current().threadTimers().nex tFireTime(); 490 if (m_webScheduler->canExceedIdleDeadlineIfRequired())
490 if (nextFireTime == 0.0 || nextFireTime > currentTime() + kMinIdleTimespan) { 491 gcDeadlineSeconds = Platform::current()->monotonicallyIncreasingTime() + kLongIdlePeriodSecs;
491 bool hasMoreWork = !isolate()->IdleNotificationDeadline(Platform::curren t()->monotonicallyIncreasingTime() + 1.0);
492 if (hasMoreWork)
493 delay = kShortIdleHandlerDelayMs;
494 }
495 492
496 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), delay); 493 if (doIdleGc(gcDeadlineSeconds))
494 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, WTF::bind<double>(&Wo rkerThread::performIdleWork, this));
495 else
496 m_webScheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&WorkerThread: :performIdleWork, this));
497 }
498
499 bool WorkerThread::doIdleGc(double deadlineSeconds)
500 {
501 bool gcFinished = false;
502 if (deadlineSeconds > Platform::current()->monotonicallyIncreasingTime())
503 gcFinished = isolate()->IdleNotificationDeadline(deadlineSeconds);
504 return gcFinished;
497 } 505 }
498 506
499 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi onContextTask> task) 507 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi onContextTask> task)
500 { 508 {
501 backingThread().postTask(location, WorkerThreadTask::create(*this, task, tru e).leakPtr()); 509 backingThread().postTask(location, WorkerThreadTask::create(*this, task, tru e).leakPtr());
502 } 510 }
503 511
504 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr< ExecutionContextTask> task, long long delayMs) 512 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr< ExecutionContextTask> task, long long delayMs)
505 { 513 {
506 backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, ta sk, true).leakPtr(), delayMs); 514 backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, ta sk, true).leakPtr(), delayMs);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); 588 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get());
581 } 589 }
582 590
583 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController) 591 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController)
584 { 592 {
585 MutexLocker locker(m_workerInspectorControllerMutex); 593 MutexLocker locker(m_workerInspectorControllerMutex);
586 m_workerInspectorController = workerInspectorController; 594 m_workerInspectorController = workerInspectorController;
587 } 595 }
588 596
589 } // namespace blink 597 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/workers/WorkerThread.h ('k') | Source/core/workers/WorkerThreadTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698