Bug 968016 - Add a parameter to SharedThreadPool to control the number of threads in the pool. r=kinteik

This commit is contained in:
Chris Pearce 2014-02-18 11:53:52 +13:00
parent 1459cdff3d
commit 898150675c
3 changed files with 54 additions and 20 deletions

View File

@ -11,7 +11,6 @@
#include "VideoUtils.h" #include "VideoUtils.h"
#include "nsXPCOMCIDInternal.h" #include "nsXPCOMCIDInternal.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "mozilla/Preferences.h"
#ifdef XP_WIN #ifdef XP_WIN
// Required to init MSCOM by MSCOMInitThreadPoolListener. // Required to init MSCOM by MSCOMInitThreadPoolListener.
@ -70,19 +69,35 @@ DestroySharedThreadPoolHashTable()
} }
TemporaryRef<SharedThreadPool> TemporaryRef<SharedThreadPool>
SharedThreadPool::Get(const nsCString& aName) SharedThreadPool::Get(const nsCString& aName, uint32_t aThreadLimit)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
EnsureInitialized(); EnsureInitialized();
MOZ_ASSERT(sMonitor); MOZ_ASSERT(sMonitor);
ReentrantMonitorAutoEnter mon(*sMonitor); ReentrantMonitorAutoEnter mon(*sMonitor);
SharedThreadPool* pool = nullptr; SharedThreadPool* pool = nullptr;
nsresult rv;
if (!sPools->Get(aName, &pool)) { if (!sPools->Get(aName, &pool)) {
nsCOMPtr<nsIThreadPool> threadPool(CreateThreadPool(aName)); nsCOMPtr<nsIThreadPool> threadPool(CreateThreadPool(aName));
NS_ENSURE_TRUE(threadPool, nullptr); NS_ENSURE_TRUE(threadPool, nullptr);
pool = new SharedThreadPool(aName, threadPool); pool = new SharedThreadPool(aName, threadPool);
// Set the thread and idle limits. Note that we don't rely on the
// EnsureThreadLimitIsAtLeast() call below, as the default thread limit
// is 4, and if aThreadLimit is less than 4 we'll end up with a pool
// with 4 threads rather than what we expected; so we'll have unexpected
// behaviour.
rv = pool->SetThreadLimit(aThreadLimit);
NS_ENSURE_SUCCESS(rv, nullptr);
rv = pool->SetIdleThreadLimit(aThreadLimit);
NS_ENSURE_SUCCESS(rv, nullptr);
sPools->Put(aName, pool); sPools->Put(aName, pool);
} else if (NS_FAILED(pool->EnsureThreadLimitIsAtLeast(aThreadLimit))) {
NS_WARNING("Failed to set limits on thread pool");
} }
MOZ_ASSERT(pool); MOZ_ASSERT(pool);
RefPtr<SharedThreadPool> instance(pool); RefPtr<SharedThreadPool> instance(pool);
return instance.forget(); return instance.forget();
@ -187,6 +202,36 @@ MSCOMInitThreadPoolListener::OnThreadShuttingDown()
#endif // XP_WIN #endif // XP_WIN
nsresult
SharedThreadPool::EnsureThreadLimitIsAtLeast(uint32_t aLimit)
{
// We limit the number of threads that we use for media. Note that we
// set the thread limit to the same as the idle limit so that we're not
// constantly creating and destroying threads (see Bug 881954). When the
// thread pool threads shutdown they dispatch an event to the main thread
// to call nsIThread::Shutdown(), and if we're very busy that can take a
// while to run, and we end up with dozens of extra threads. Note that
// threads that are idle for 60 seconds are shutdown naturally.
uint32_t existingLimit = 0;
nsresult rv;
rv = mPool->GetThreadLimit(&existingLimit);
NS_ENSURE_SUCCESS(rv, rv);
if (aLimit > existingLimit) {
rv = mPool->SetThreadLimit(aLimit);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mPool->GetIdleThreadLimit(&existingLimit);
NS_ENSURE_SUCCESS(rv, rv);
if (aLimit > existingLimit) {
rv = mPool->SetIdleThreadLimit(aLimit);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
static already_AddRefed<nsIThreadPool> static already_AddRefed<nsIThreadPool>
CreateThreadPool(const nsCString& aName) CreateThreadPool(const nsCString& aName)
{ {
@ -199,21 +244,6 @@ CreateThreadPool(const nsCString& aName)
rv = pool->SetName(aName); rv = pool->SetName(aName);
NS_ENSURE_SUCCESS(rv, nullptr); NS_ENSURE_SUCCESS(rv, nullptr);
// We limit the number of threads that we use for media. Note that the
// default thread limit is the same as the idle limit so that we're not
// constantly creating and destroying threads (see Bug 881954). When the
// thread pool threads shutdown they dispatch an event to the main thread
// to call nsIThread::Shutdown(), and if we're very busy that can take a
// while to run, and we end up with dozens of extra threads. Note that
// threads that are idle for 60 seconds are shutdown naturally.
rv = pool->SetThreadLimit(
Preferences::GetUint("media.thread-pool.thread-limit", 4));
NS_ENSURE_SUCCESS(rv, nullptr);
rv = pool->SetIdleThreadLimit(
Preferences::GetUint("media.thread-pool.idle-thread-limit", 4));
NS_ENSURE_SUCCESS(rv, nullptr);
#ifdef XP_WIN #ifdef XP_WIN
// Ensure MSCOM is initialized on the thread pools threads. // Ensure MSCOM is initialized on the thread pools threads.
nsCOMPtr<nsIThreadPoolListener> listener = new MSCOMInitThreadPoolListener(); nsCOMPtr<nsIThreadPoolListener> listener = new MSCOMInitThreadPoolListener();

View File

@ -31,7 +31,8 @@ public:
// Gets (possibly creating) the shared thread pool singleton instance with // Gets (possibly creating) the shared thread pool singleton instance with
// thread pool named aName. // thread pool named aName.
// *Must* be called on the main thread. // *Must* be called on the main thread.
static TemporaryRef<SharedThreadPool> Get(const nsCString& aName); static TemporaryRef<SharedThreadPool> Get(const nsCString& aName,
uint32_t aThreadLimit = 4);
// We implement custom threadsafe AddRef/Release pair, that destroys the // We implement custom threadsafe AddRef/Release pair, that destroys the
// the shared pool singleton when the refcount drops to 0. The addref/release // the shared pool singleton when the refcount drops to 0. The addref/release
@ -54,9 +55,12 @@ private:
// Creates a singleton SharedThreadPool wrapper around aPool. // Creates a singleton SharedThreadPool wrapper around aPool.
// aName is the name of the aPool, and is used to lookup the // aName is the name of the aPool, and is used to lookup the
// SharedThreadPool in the hash table of all created pools. // SharedThreadPool in the hash table of all created pools.
SharedThreadPool(const nsCString& aName, nsIThreadPool* aPool); SharedThreadPool(const nsCString& aName,
nsIThreadPool* aPool);
virtual ~SharedThreadPool(); virtual ~SharedThreadPool();
nsresult EnsureThreadLimitIsAtLeast(uint32_t aThreadLimit);
// Name of mPool. // Name of mPool.
const nsCString mName; const nsCString mName;

View File

@ -63,7 +63,7 @@ WMFByteStream::Init()
{ {
NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); NS_ASSERTION(NS_IsMainThread(), "Must be on main thread.");
mThreadPool = SharedThreadPool::Get(NS_LITERAL_CSTRING("WMFByteStream IO")); mThreadPool = SharedThreadPool::Get(NS_LITERAL_CSTRING("WMFByteStream IO"), 4);
NS_ENSURE_TRUE(mThreadPool, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mThreadPool, NS_ERROR_FAILURE);
NS_ConvertUTF8toUTF16 contentTypeUTF16(mResource->GetContentType()); NS_ConvertUTF8toUTF16 contentTypeUTF16(mResource->GetContentType());