зеркало из https://github.com/mozilla/gecko-dev.git
bug 692260 - pr_poll limit autodiscovery for windows r=jduell
--HG-- extra : rebase_source : dc9b024b4004e0a4025e843e94e046b4dd69dca9
This commit is contained in:
Родитель
6bd2493132
Коммит
7bd44a1858
|
@ -85,6 +85,7 @@ nsSocketTransportService::nsSocketTransportService()
|
|||
, mActiveCount(0)
|
||||
, mIdleCount(0)
|
||||
, mSendBufferSize(0)
|
||||
, mProbedMaxCount(false)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
gSocketTransportLog = PR_NewLogModule("nsSocketTransport");
|
||||
|
@ -719,6 +720,14 @@ nsSocketTransportService::DoPollIteration(bool wait)
|
|||
|
||||
SOCKET_LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount));
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// 30 active connections is the historic limit before firefox 7's 256. A few
|
||||
// windows systems have troubles with the higher limit, so actively probe a
|
||||
// limit the first time we exceed 30.
|
||||
if ((mActiveCount > 30) && !mProbedMaxCount)
|
||||
ProbeMaxCount();
|
||||
#endif
|
||||
|
||||
// Measures seconds spent while blocked on PR_Poll
|
||||
PRUint32 pollInterval;
|
||||
|
||||
|
@ -835,6 +844,73 @@ nsSocketTransportService::GetSendBufferSize(PRInt32 *value)
|
|||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
// Right now the only need to do this is on windows.
|
||||
#if defined(XP_WIN)
|
||||
void
|
||||
nsSocketTransportService::ProbeMaxCount()
|
||||
{
|
||||
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||
|
||||
if (mProbedMaxCount)
|
||||
return;
|
||||
mProbedMaxCount = true;
|
||||
|
||||
PRInt32 startedMaxCount = gMaxCount;
|
||||
|
||||
// Allocate and test a PR_Poll up to the gMaxCount number of unconnected
|
||||
// sockets. See bug 692260 - windows should be able to handle 1000 sockets
|
||||
// in select() without a problem, but LSPs have been known to balk at lower
|
||||
// numbers. (64 in the bug).
|
||||
|
||||
// Allocate
|
||||
struct PRPollDesc pfd[SOCKET_LIMIT_TARGET];
|
||||
PRUint32 numAllocated = 0;
|
||||
|
||||
for (PRUint32 index = 0 ; index < gMaxCount; ++index) {
|
||||
pfd[index].in_flags = PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT;
|
||||
pfd[index].out_flags = 0;
|
||||
pfd[index].fd = PR_OpenTCPSocket(PR_AF_INET);
|
||||
if (!pfd[index].fd) {
|
||||
SOCKET_LOG(("Socket Limit Test index %d failed\n", index));
|
||||
if (index < SOCKET_LIMIT_MIN)
|
||||
gMaxCount = SOCKET_LIMIT_MIN;
|
||||
else
|
||||
gMaxCount = index;
|
||||
break;
|
||||
}
|
||||
++numAllocated;
|
||||
}
|
||||
|
||||
// Test
|
||||
PR_STATIC_ASSERT(SOCKET_LIMIT_MIN >= 32U);
|
||||
while (gMaxCount <= numAllocated) {
|
||||
PRInt32 rv = PR_Poll(pfd, gMaxCount, PR_MillisecondsToInterval(0));
|
||||
|
||||
SOCKET_LOG(("Socket Limit Test poll() size=%d rv=%d\n",
|
||||
gMaxCount, rv));
|
||||
|
||||
if (rv >= 0)
|
||||
break;
|
||||
|
||||
SOCKET_LOG(("Socket Limit Test poll confirmationSize=%d rv=%d error=%d\n",
|
||||
gMaxCount, rv, PR_GetError()));
|
||||
|
||||
gMaxCount -= 32;
|
||||
if (gMaxCount <= SOCKET_LIMIT_MIN) {
|
||||
gMaxCount = SOCKET_LIMIT_MIN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Free
|
||||
for (PRUint32 index = 0 ; index < numAllocated; ++index)
|
||||
if (pfd[index].fd)
|
||||
PR_Close(pfd[index].fd);
|
||||
|
||||
SOCKET_LOG(("Socket Limit Test max was confirmed at %d\n", gMaxCount));
|
||||
}
|
||||
#endif // windows
|
||||
|
||||
PRStatus
|
||||
nsSocketTransportService::DiscoverMaxCount()
|
||||
{
|
||||
|
|
|
@ -205,6 +205,12 @@ private:
|
|||
// Preference Monitor for SendBufferSize
|
||||
nsresult UpdatePrefs();
|
||||
PRInt32 mSendBufferSize;
|
||||
|
||||
// Socket thread only for dynamically adjusting max socket size
|
||||
#if defined(XP_WIN)
|
||||
void ProbeMaxCount();
|
||||
#endif
|
||||
bool mProbedMaxCount;
|
||||
};
|
||||
|
||||
extern nsSocketTransportService *gSocketTransportService;
|
||||
|
|
|
@ -646,6 +646,16 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 cap
|
|||
LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n",
|
||||
ci->HashKey().get(), caps));
|
||||
|
||||
// update maxconns if potentially limited by the max socket count
|
||||
// this requires a dynamic reduction in the max socket count to a point
|
||||
// lower than the max-connections pref.
|
||||
PRUint32 maxSocketCount = gHttpHandler->MaxSocketCount();
|
||||
if (mMaxConns > maxSocketCount) {
|
||||
mMaxConns = maxSocketCount;
|
||||
LOG(("nsHttpConnectionMgr %p mMaxConns dynamically reduced to %u",
|
||||
this, mMaxConns));
|
||||
}
|
||||
|
||||
// If there are more active connections than the global limit, then we're
|
||||
// done. Purging idle connections won't get us below it.
|
||||
if (mNumActiveConns >= mMaxConns) {
|
||||
|
|
|
@ -773,6 +773,24 @@ nsHttpHandler::InitUserAgentComponents()
|
|||
mUserAgentIsDirty = true;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsHttpHandler::MaxSocketCount()
|
||||
{
|
||||
PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce,
|
||||
nsSocketTransportService::DiscoverMaxCount);
|
||||
// Don't use the full max count because sockets can be held in
|
||||
// the persistent connection pool for a long time and that could
|
||||
// starve other users.
|
||||
|
||||
PRUint32 maxCount = nsSocketTransportService::gMaxCount;
|
||||
if (maxCount <= 8)
|
||||
maxCount = 1;
|
||||
else
|
||||
maxCount -= 8;
|
||||
|
||||
return maxCount;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||
{
|
||||
|
@ -837,11 +855,10 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
|||
if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
|
||||
rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce,
|
||||
nsSocketTransportService::DiscoverMaxCount);
|
||||
mMaxConnections =
|
||||
(PRUint16) NS_CLAMP((PRUint32)val, 1,
|
||||
nsSocketTransportService::gMaxCount);
|
||||
|
||||
mMaxConnections = (PRUint16) NS_CLAMP((PRUint32)val,
|
||||
1, MaxSocketCount());
|
||||
|
||||
if (mConnMgr)
|
||||
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
|
||||
mMaxConnections);
|
||||
|
|
|
@ -108,6 +108,7 @@ public:
|
|||
PRUint8 GetQoSBits() { return mQoSBits; }
|
||||
PRUint16 GetIdleSynTimeout() { return mIdleSynTimeout; }
|
||||
bool FastFallbackToIPv4() { return mFastFallbackToIPv4; }
|
||||
PRUint32 MaxSocketCount();
|
||||
|
||||
bool IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; }
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче