Changeset 207480 in webkit
- Timestamp:
- Oct 18, 2016 1:17:10 PM (8 years ago)
- Location:
- trunk/Source
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r207476 r207480 1 2016-10-18 Filip Pizlo <fpizlo@apple.com> 2 3 WTF should make it easier to create threads that die automatically after inactivity 4 https://bugs.webkit.org/show_bug.cgi?id=163576 5 6 Reviewed by Andreas Kling. 7 8 Added a sleepSeconds() function, which made it easier for me to test this change. 9 10 The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now 11 shut down automatically after 1 second of inactivity. Maybe this will save some memory. 12 13 * jsc.cpp: 14 (GlobalObject::finishCreation): 15 (functionSleepSeconds): 16 1 17 2016-10-18 Keith Miller <keith_miller@apple.com> 2 18 -
trunk/Source/JavaScriptCore/jsc.cpp
r207456 r207480 844 844 static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*); 845 845 static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*); 846 static EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState*); 846 847 static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*); 847 848 static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*); … … 1068 1069 addFunction(vm, "read", functionReadFile, 2); 1069 1070 addFunction(vm, "checkSyntax", functionCheckSyntax, 1); 1071 addFunction(vm, "sleepSeconds", functionSleepSeconds, 1); 1070 1072 addFunction(vm, "jscStack", functionJSCStack, 1); 1071 1073 addFunction(vm, "readline", functionReadline, 0); … … 1494 1496 } 1495 1497 1498 EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState* exec) 1499 { 1500 if (exec->argumentCount() >= 1) 1501 sleep(exec->argument(0).toNumber(exec)); 1502 return JSValue::encode(jsUndefined()); 1503 } 1504 1496 1505 class FunctionJSCStackFunctor { 1497 1506 public: -
trunk/Source/WTF/ChangeLog
r207471 r207480 1 2016-10-18 Filip Pizlo <fpizlo@apple.com> 2 3 WTF should make it easier to create threads that die automatically after inactivity 4 https://bugs.webkit.org/show_bug.cgi?id=163576 5 6 Reviewed by Andreas Kling. 7 8 For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel 9 guilty because those threads don't shut down when they are inactive. For example, in bug 10 163562, I need to add a new GC thread. There will be one of them per VM. This means that a 11 JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's 12 good. 13 14 A common pattern for all of these threads is that they have some well-defined trigger that 15 causes them to run. This trigger has a lock, a condition variable, some logic that determines 16 if there is work to do, and then of course the logic for the thread's actual work. The thread 17 bodies usually look like this: 18 19 void Thingy::runThread() 20 { 21 for (;;) { 22 Work work; 23 { 24 LockHolder locker(m_lock); 25 while (!hasWork()) 26 m_cond.wait(m_lock); 27 work = takeWork(); 28 } 29 doWork(work); 30 } 31 } 32 33 If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's 34 threads), you will see this pattern. 35 36 This change adds a new kind of thread, called AutomaticThread, that lets you write threads to 37 this pattern while getting automatic thread shutdown for free: instead of just waiting on a 38 condition variable, AutomaticThread will have a timeout that causes the thread to die. The 39 condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart 40 enough to restart any threads that have decided to stop due to inactivity. The inactivity 41 threshold is current just 1 second. 42 43 In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more 44 places soon. 45 46 * WTF.xcodeproj/project.pbxproj: 47 * wtf/AutomaticThread.cpp: Added. 48 (WTF::AutomaticThreadCondition::create): 49 (WTF::AutomaticThreadCondition::AutomaticThreadCondition): 50 (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): 51 (WTF::AutomaticThreadCondition::notifyAll): 52 (WTF::AutomaticThreadCondition::add): 53 (WTF::AutomaticThreadCondition::remove): 54 (WTF::AutomaticThreadCondition::contains): 55 (WTF::AutomaticThread::AutomaticThread): 56 (WTF::AutomaticThread::~AutomaticThread): 57 (WTF::AutomaticThread::join): 58 (WTF::AutomaticThread::start): 59 * wtf/AutomaticThread.h: Added. 60 * wtf/CMakeLists.txt: 61 * wtf/ParallelHelperPool.cpp: 62 (WTF::ParallelHelperClient::ParallelHelperClient): 63 (WTF::ParallelHelperClient::~ParallelHelperClient): 64 (WTF::ParallelHelperClient::setTask): 65 (WTF::ParallelHelperClient::finish): 66 (WTF::ParallelHelperClient::doSomeHelping): 67 (WTF::ParallelHelperClient::runTask): 68 (WTF::ParallelHelperPool::ParallelHelperPool): 69 (WTF::ParallelHelperPool::~ParallelHelperPool): 70 (WTF::ParallelHelperPool::ensureThreads): 71 (WTF::ParallelHelperPool::doSomeHelping): 72 (WTF::ParallelHelperPool::Thread::Thread): 73 (WTF::ParallelHelperPool::didMakeWorkAvailable): 74 (WTF::ParallelHelperPool::helperThreadBody): Deleted. 75 (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. 76 * wtf/ParallelHelperPool.h: 77 1 78 2016-10-18 Said Abou-Hallawa <sabouhallawa@apple.com> 2 79 -
trunk/Source/WTF/WTF.xcodeproj/project.pbxproj
r207156 r207480 26 26 0F2B66A717B6B4FD00A7AE3F /* FlipBytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */; }; 27 27 0F3501641BB258D500F0A2A3 /* WeakRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3501631BB258C800F0A2A3 /* WeakRandom.h */; }; 28 0F43D8F11DB5ADDC00108FB6 /* AutomaticThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F43D8EF1DB5ADDC00108FB6 /* AutomaticThread.cpp */; }; 29 0F43D8F21DB5ADDC00108FB6 /* AutomaticThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F43D8F01DB5ADDC00108FB6 /* AutomaticThread.h */; }; 28 30 0F4570431BE5B58F0062A629 /* Dominators.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4570421BE5B58F0062A629 /* Dominators.h */; }; 29 31 0F4570451BE834410062A629 /* BubbleSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4570441BE834410062A629 /* BubbleSort.h */; }; … … 367 369 0F300B7D18AB48B400A6D72E /* HashMethod.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HashMethod.h; sourceTree = "<group>"; }; 368 370 0F3501631BB258C800F0A2A3 /* WeakRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakRandom.h; sourceTree = "<group>"; }; 371 0F43D8EF1DB5ADDC00108FB6 /* AutomaticThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AutomaticThread.cpp; sourceTree = "<group>"; }; 372 0F43D8F01DB5ADDC00108FB6 /* AutomaticThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutomaticThread.h; sourceTree = "<group>"; }; 369 373 0F4570421BE5B58F0062A629 /* Dominators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dominators.h; sourceTree = "<group>"; }; 370 374 0F4570441BE834410062A629 /* BubbleSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BubbleSort.h; sourceTree = "<group>"; }; … … 840 844 1469419A16EAB10A0024E146 /* AutodrainedPool.h */, 841 845 1469419B16EAB10A0024E146 /* AutodrainedPoolMac.mm */, 846 0F43D8EF1DB5ADDC00108FB6 /* AutomaticThread.cpp */, 847 0F43D8F01DB5ADDC00108FB6 /* AutomaticThread.h */, 842 848 DCEE22041CEB9869000C2396 /* BackwardsGraph.h */, 843 849 0FB14E18180FA218009B6B4D /* Bag.h */, … … 1331 1337 7CDD7FF8186D291E007433CD /* IteratorAdaptors.h in Headers */, 1332 1338 7CDD7FFA186D2A54007433CD /* IteratorRange.h in Headers */, 1339 0F43D8F21DB5ADDC00108FB6 /* AutomaticThread.h in Headers */, 1333 1340 93AC91A818942FC400244939 /* LChar.h in Headers */, 1334 1341 539EB0631D55284200C82EF7 /* LEBDecoder.h in Headers */, … … 1635 1642 0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */, 1636 1643 A8A47443151A825B004123FF /* StringStatics.cpp in Sources */, 1644 0F43D8F11DB5ADDC00108FB6 /* AutomaticThread.cpp in Sources */, 1637 1645 93F1993E19D7958D00C2390B /* StringView.cpp in Sources */, 1638 1646 93934BD518A1F16900D0D6A1 /* StringViewCF.cpp in Sources */, -
trunk/Source/WTF/wtf/CMakeLists.txt
r206691 r207480 3 3 Assertions.h 4 4 Atomics.h 5 AutomaticThread.h 5 6 BackwardsGraph.h 6 7 Bag.h … … 174 175 Assertions.cpp 175 176 Atomics.cpp 177 AutomaticThread.cpp 176 178 BitVector.cpp 177 179 CompilationThread.cpp -
trunk/Source/WTF/wtf/ParallelHelperPool.cpp
r190875 r207480 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #include "ParallelHelperPool.h" 28 28 29 #include "AutomaticThread.h" 29 30 #include "DataLog.h" 30 31 #include "StringPrintStream.h" … … 35 36 : m_pool(pool) 36 37 { 37 LockHolder locker( m_pool->m_lock);38 LockHolder locker(*m_pool->m_lock); 38 39 RELEASE_ASSERT(!m_pool->m_isDying); 39 40 m_pool->m_clients.append(this); … … 42 43 ParallelHelperClient::~ParallelHelperClient() 43 44 { 44 LockHolder locker( m_pool->m_lock);45 LockHolder locker(*m_pool->m_lock); 45 46 finish(locker); 46 47 … … 56 57 void ParallelHelperClient::setTask(RefPtr<SharedTask<void ()>> task) 57 58 { 58 LockHolder locker( m_pool->m_lock);59 LockHolder locker(*m_pool->m_lock); 59 60 RELEASE_ASSERT(!m_task); 60 61 m_task = task; … … 64 65 void ParallelHelperClient::finish() 65 66 { 66 LockHolder locker( m_pool->m_lock);67 LockHolder locker(*m_pool->m_lock); 67 68 finish(locker); 68 69 } … … 72 73 RefPtr<SharedTask<void ()>> task; 73 74 { 74 LockHolder locker( m_pool->m_lock);75 LockHolder locker(*m_pool->m_lock); 75 76 task = claimTask(locker); 76 77 if (!task) … … 92 93 m_task = nullptr; 93 94 while (m_numActive) 94 m_pool->m_workCompleteCondition.wait( m_pool->m_lock);95 m_pool->m_workCompleteCondition.wait(*m_pool->m_lock); 95 96 } 96 97 … … 112 113 113 114 { 114 LockHolder locker( m_pool->m_lock);115 LockHolder locker(*m_pool->m_lock); 115 116 RELEASE_ASSERT(m_numActive); 116 117 // No new task could have been installed, since we were still active. … … 124 125 125 126 ParallelHelperPool::ParallelHelperPool() 127 : m_lock(Box<Lock>::create()) 128 , m_workAvailableCondition(AutomaticThreadCondition::create()) 126 129 { 127 130 } … … 132 135 133 136 { 134 LockHolder locker( m_lock);137 LockHolder locker(*m_lock); 135 138 m_isDying = true; 136 m_workAvailableCondition .notifyAll();137 } 138 139 for ( ThreadIdentifier threadIdentifier: m_threads)140 waitForThreadCompletion(threadIdentifier);139 m_workAvailableCondition->notifyAll(locker); 140 } 141 142 for (RefPtr<AutomaticThread>& thread : m_threads) 143 thread->join(); 141 144 } 142 145 143 146 void ParallelHelperPool::ensureThreads(unsigned numThreads) 144 147 { 145 LockHolder locker( m_lock);148 LockHolder locker(*m_lock); 146 149 if (numThreads < m_numThreads) 147 150 return; … … 156 159 RefPtr<SharedTask<void ()>> task; 157 160 { 158 LockHolder locker( m_lock);161 LockHolder locker(*m_lock); 159 162 client = getClientWithTask(locker); 160 163 if (!client) … … 166 169 } 167 170 168 void ParallelHelperPool::didMakeWorkAvailable(const LockHolder&) 169 { 170 while (m_numThreads > m_threads.size()) { 171 ThreadIdentifier threadIdentifier = createThread( 172 "WTF Parallel Helper Thread", 173 [this] () { 174 helperThreadBody(); 175 }); 176 m_threads.append(threadIdentifier); 177 } 178 m_workAvailableCondition.notifyAll(); 179 } 180 181 void ParallelHelperPool::helperThreadBody() 182 { 183 for (;;) { 184 ParallelHelperClient* client; 185 RefPtr<SharedTask<void ()>> task; 186 187 { 188 LockHolder locker(m_lock); 189 client = waitForClientWithTask(locker); 190 if (!client) { 191 RELEASE_ASSERT(m_isDying); 192 return; 193 } 194 195 task = client->claimTask(locker); 171 class ParallelHelperPool::Thread : public AutomaticThread { 172 public: 173 Thread(const LockHolder& locker, ParallelHelperPool& pool) 174 : AutomaticThread(locker, pool.m_lock, pool.m_workAvailableCondition) 175 , m_pool(pool) 176 { 177 } 178 179 protected: 180 PollResult poll(const LockHolder& locker) override 181 { 182 if (m_pool.m_isDying) 183 return PollResult::Stop; 184 m_client = m_pool.getClientWithTask(locker); 185 if (m_client) { 186 m_task = m_client->claimTask(locker); 187 return PollResult::Work; 196 188 } 197 198 client->runTask(task); 199 } 189 return PollResult::Wait; 190 } 191 192 WorkResult work() override 193 { 194 m_client->runTask(m_task); 195 m_client = nullptr; 196 m_task = nullptr; 197 return WorkResult::Continue; 198 } 199 200 private: 201 ParallelHelperPool& m_pool; 202 ParallelHelperClient* m_client { nullptr }; 203 RefPtr<SharedTask<void ()>> m_task; 204 }; 205 206 void ParallelHelperPool::didMakeWorkAvailable(const LockHolder& locker) 207 { 208 while (m_numThreads > m_threads.size()) 209 m_threads.append(adoptRef(new Thread(locker, *this))); 210 m_workAvailableCondition->notifyAll(locker); 200 211 } 201 212 … … 223 234 } 224 235 225 ParallelHelperClient* ParallelHelperPool::waitForClientWithTask(const LockHolder& locker)226 {227 for (;;) {228 // It might be quittin' time.229 if (m_isDying)230 return nullptr;231 232 if (ParallelHelperClient* result = getClientWithTask(locker))233 return result;234 235 // Wait until work becomes available.236 m_workAvailableCondition.wait(m_lock);237 }238 }239 240 236 } // namespace WTF 241 237 -
trunk/Source/WTF/wtf/ParallelHelperPool.h
r190875 r207480 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #define ParallelHelperPool_h 28 28 29 #include <wtf/Box.h> 29 30 #include <wtf/Condition.h> 30 31 #include <wtf/Lock.h> … … 37 38 38 39 namespace WTF { 40 41 class AutomaticThread; 42 class AutomaticThreadCondition; 39 43 40 44 // A ParallelHelperPool is a shared pool of threads that can be asked to help with some finite-time … … 187 191 private: 188 192 friend class ParallelHelperClient; 193 class Thread; 194 friend class Thread; 189 195 190 196 void didMakeWorkAvailable(const LockHolder&); 191 void helperThreadBody();192 197 193 198 bool hasClientWithTask(const LockHolder&); … … 195 200 ParallelHelperClient* waitForClientWithTask(const LockHolder&); 196 201 197 Lock m_lock;198 Conditionm_workAvailableCondition;202 Box<Lock> m_lock; // AutomaticThread wants this in a box for safety. 203 RefPtr<AutomaticThreadCondition> m_workAvailableCondition; 199 204 Condition m_workCompleteCondition; 200 205 … … 202 207 203 208 Vector<ParallelHelperClient*> m_clients; 204 Vector< ThreadIdentifier> m_threads;209 Vector<RefPtr<AutomaticThread>> m_threads; 205 210 unsigned m_numThreads { 0 }; // This can be larger than m_threads.size() because we start threads only once there is work. 206 211 bool m_isDying { false };
Note: See TracChangeset
for help on using the changeset viewer.