author | Dragana Damjanovic <dd.mozilla@gmail.com> |
Wed, 04 Mar 2015 14:17:00 +0100 | |
changeset 231986 | 7d6ee599c58b249b9bc0220bba7ff39ec787265f |
parent 231985 | c6d4680f1f5a7494ffbbe61dba8196c06ee60b2d |
child 231987 | 54eee85f489fb01da314d4242fed398fdad72b29 |
push id | 56423 |
push user | cbook@mozilla.com |
push date | Thu, 05 Mar 2015 11:30:52 +0000 |
treeherder | mozilla-inbound@1968388d42c2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mcmanus |
bugs | 1131557 |
milestone | 39.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1355,16 +1355,22 @@ pref("network.http.enforce-framing.soft" // default values for FTP // in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594, // Section 4.8 "High-Throughput Data Service Class", and 80 (0x50, or AF22) // per Section 4.7 "Low-Latency Data Service Class". pref("network.ftp.data.qos", 0); pref("network.ftp.control.qos", 0); +// If this pref is false only one xpcom event will be served per poll +// iteration. This is the original behavior. +// If it is true multiple events will be served. +pref("network.sts.serve_multiple_events_per_poll_iteration", true); +// The max time to spend on xpcom events between two polls in ms. +pref("network.sts.max_time_for_events_between_two_polls", 100); // </http> // 2147483647 == PR_INT32_MAX == ~2 GB pref("network.websocket.max-message-size", 2147483647); // Should we automatically follow http 3xx redirects during handshake pref("network.websocket.auto-follow-http-redirects", false);
--- a/netwerk/base/nsSocketTransportService2.cpp +++ b/netwerk/base/nsSocketTransportService2.cpp @@ -14,16 +14,17 @@ #include "NetworkActivityMonitor.h" #include "nsIObserverService.h" #include "mozilla/Services.h" #include "mozilla/Preferences.h" #include "mozilla/Likely.h" #include "mozilla/PublicSSL.h" #include "mozilla/ChaosMode.h" #include "mozilla/PodOperations.h" +#include "mozilla/TimeStamp.h" #include "nsThreadUtils.h" #include "nsIFile.h" using namespace mozilla; using namespace mozilla::net; #if defined(PR_LOGGING) PRLogModuleInfo *gSocketTransportLog = nullptr; @@ -35,16 +36,18 @@ PRThread *gSocketThread #define SEND_BUFFER_PREF "network.tcp.sendbuffer" #define KEEPALIVE_ENABLED_PREF "network.tcp.keepalive.enabled" #define KEEPALIVE_IDLE_TIME_PREF "network.tcp.keepalive.idle_time" #define KEEPALIVE_RETRY_INTERVAL_PREF "network.tcp.keepalive.retry_interval" #define KEEPALIVE_PROBE_COUNT_PREF "network.tcp.keepalive.probe_count" #define SOCKET_LIMIT_TARGET 550U #define SOCKET_LIMIT_MIN 50U #define BLIP_INTERVAL_PREF "network.activity.blipIntervalMilliseconds" +#define SERVE_MULTIPLE_EVENTS_PREF "network.sts.serve_multiple_events_per_poll_iteration" +#define MAX_TIME_BETWEEN_TWO_POLLS "network.sts.max_time_for_events_between_two_polls" uint32_t nsSocketTransportService::gMaxCount; PRCallOnceType nsSocketTransportService::gMaxCountInitOnce; //----------------------------------------------------------------------------- // ctor/dtor (called on the main/UI thread by the service manager) nsSocketTransportService::nsSocketTransportService() @@ -62,16 +65,19 @@ nsSocketTransportService::nsSocketTransp , mIdleCount(0) , mSentBytesCount(0) , mReceivedBytesCount(0) , mSendBufferSize(0) , mKeepaliveIdleTimeS(600) , mKeepaliveRetryIntervalS(1) , mKeepaliveProbeCount(kDefaultTCPKeepCount) , mKeepaliveEnabledPref(false) + , mServeMultipleEventsPerPollIter(true) + , mServingPendingQueue(false) + , mMaxTimePerPollIter(100) , mProbedMaxCount(false) { #if defined(PR_LOGGING) gSocketTransportLog = PR_NewLogModule("nsSocketTransport"); #endif NS_ASSERTION(NS_IsMainThread(), "wrong thread"); @@ -476,16 +482,18 @@ nsSocketTransportService::Init() nsCOMPtr<nsIPrefBranch> tmpPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID); if (tmpPrefService) { tmpPrefService->AddObserver(SEND_BUFFER_PREF, this, false); tmpPrefService->AddObserver(KEEPALIVE_ENABLED_PREF, this, false); tmpPrefService->AddObserver(KEEPALIVE_IDLE_TIME_PREF, this, false); tmpPrefService->AddObserver(KEEPALIVE_RETRY_INTERVAL_PREF, this, false); tmpPrefService->AddObserver(KEEPALIVE_PROBE_COUNT_PREF, this, false); + tmpPrefService->AddObserver(SERVE_MULTIPLE_EVENTS_PREF, this, false); + tmpPrefService->AddObserver(MAX_TIME_BETWEEN_TWO_POLLS, this, false); } UpdatePrefs(); nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService(); if (obsSvc) { obsSvc->AddObserver(this, "profile-initial-state", false); obsSvc->AddObserver(this, "last-pb-context-exited", false); } @@ -681,16 +689,22 @@ nsSocketTransportService::OnProcessNextE NS_IMETHODIMP nsSocketTransportService::AfterProcessNextEvent(nsIThreadInternal* thread, uint32_t depth, bool eventWasProcessed) { return NS_OK; } +void +nsSocketTransportService::MarkTheLastElementOfPendingQueue() +{ + mServingPendingQueue = false; +} + #ifdef MOZ_NUWA_PROCESS #include "ipc/Nuwa.h" #endif NS_IMETHODIMP nsSocketTransportService::Run() { PR_SetCurrentThreadName("Socket Thread"); @@ -725,25 +739,49 @@ nsSocketTransportService::Run() for (;;) { bool pendingEvents = false; thread->HasPendingEvents(&pendingEvents); do { // If there are pending events for this thread then // DoPollIteration() should service the network without blocking. DoPollIteration(!pendingEvents); - + // If nothing was pending before the poll, it might be now - if (!pendingEvents) + if (!pendingEvents) { thread->HasPendingEvents(&pendingEvents); + } if (pendingEvents) { - NS_ProcessNextEvent(thread); - pendingEvents = false; - thread->HasPendingEvents(&pendingEvents); + if (mServeMultipleEventsPerPollIter) { + if (!mServingPendingQueue) { + nsresult rv = Dispatch(NS_NewRunnableMethod(this, + &nsSocketTransportService::MarkTheLastElementOfPendingQueue), + nsIEventTarget::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING("Could not dispatch a new event on the " + "socket thread."); + } else { + mServingPendingQueue = true; + } + } + TimeStamp eventQueueStart = TimeStamp::NowLoRes(); + do { + NS_ProcessNextEvent(thread); + pendingEvents = false; + thread->HasPendingEvents(&pendingEvents); + } while (pendingEvents && mServingPendingQueue && + ((TimeStamp::NowLoRes() - + eventQueueStart).ToMilliseconds() < + mMaxTimePerPollIter)); + } else { + NS_ProcessNextEvent(thread); + pendingEvents = false; + thread->HasPendingEvents(&pendingEvents); + } } } while (pendingEvents); bool goingOffline = false; // now that our event queue is empty, check to see if we should exit { MutexAutoLock lock(mLock); if (mShuttingDown) @@ -977,16 +1015,30 @@ nsSocketTransportService::UpdatePrefs() 1, kMaxTCPKeepCount); bool keepaliveEnabled = false; rv = tmpPrefService->GetBoolPref(KEEPALIVE_ENABLED_PREF, &keepaliveEnabled); if (NS_SUCCEEDED(rv) && keepaliveEnabled != mKeepaliveEnabledPref) { mKeepaliveEnabledPref = keepaliveEnabled; OnKeepaliveEnabledPrefChange(); } + + bool serveMultiplePref = false; + rv = tmpPrefService->GetBoolPref(SERVE_MULTIPLE_EVENTS_PREF, + &serveMultiplePref); + if (NS_SUCCEEDED(rv)) { + mServeMultipleEventsPerPollIter = serveMultiplePref; + } + + int32_t maxTimePref; + rv = tmpPrefService->GetIntPref(MAX_TIME_BETWEEN_TWO_POLLS, + &maxTimePref); + if (NS_SUCCEEDED(rv) && maxTimePref >= 0) { + mMaxTimePerPollIter = maxTimePref; + } } return NS_OK; } void nsSocketTransportService::OnKeepaliveEnabledPrefChange() {
--- a/netwerk/base/nsSocketTransportService2.h +++ b/netwerk/base/nsSocketTransportService2.h @@ -12,16 +12,17 @@ #include "nsEventQueue.h" #include "nsCOMPtr.h" #include "prinrval.h" #include "prlog.h" #include "prinit.h" #include "nsIObserver.h" #include "mozilla/Mutex.h" #include "mozilla/net/DashboardTypes.h" +#include "mozilla/Atomics.h" class nsASocketHandler; struct PRPollDesc; //----------------------------------------------------------------------------- #if defined(PR_LOGGING) // @@ -212,30 +213,36 @@ private: int32_t mKeepaliveIdleTimeS; // Number of seconds between retries should keepalive pings fail. int32_t mKeepaliveRetryIntervalS; // Number of keepalive probes to send. int32_t mKeepaliveProbeCount; // True if TCP keepalive is enabled globally. bool mKeepaliveEnabledPref; + bool mServeMultipleEventsPerPollIter; + mozilla::Atomic<bool> mServingPendingQueue; + int32_t mMaxTimePerPollIter; + void OnKeepaliveEnabledPrefChange(); void NotifyKeepaliveEnabledPrefChange(SocketContext *sock); // Socket thread only for dynamically adjusting max socket size #if defined(XP_WIN) void ProbeMaxCount(); #endif bool mProbedMaxCount; void AnalyzeConnection(nsTArray<mozilla::net::SocketInfo> *data, SocketContext *context, bool aActive); void ClosePrivateConnections(); void DetachSocketWithGuard(bool aGuardLocals, SocketContext *socketList, int32_t index); + + void MarkTheLastElementOfPendingQueue(); }; extern nsSocketTransportService *gSocketTransportService; extern PRThread *gSocketThread; #endif // !nsSocketTransportService_h__