Commit ea8cc58c authored by Patrick McManus's avatar Patrick McManus
Browse files

Bug 1260218 - SocketTransportService socket expansion r=dragana

parent ec0cba0f
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -1323,10 +1323,13 @@ pref("network.http.keep-alive.timeout", 115);
pref("network.http.response.timeout", 300);

// Limit the absolute number of http connections.
// Note: the socket transport service will clamp the number below 256 if the OS
// cannot allocate that many FDs, and it also always tries to reserve up to 250
// file descriptors for things other than sockets.
// Note: the socket transport service will clamp the number below this if the OS
// cannot allocate that many FDs
#ifdef ANDROID
pref("network.http.max-connections", 256);
#else
pref("network.http.max-connections", 900);
#endif

// If NOT connecting via a proxy, then
// a new connection will only be attempted if the number of active persistent
+58 −22
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ Atomic<PRThread*, Relaxed> gSocketThread;
#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_TARGET 1000U
#define SOCKET_LIMIT_MIN      50U
#define BLIP_INTERVAL_PREF "network.activity.blipIntervalMilliseconds"
#define MAX_TIME_BETWEEN_TWO_POLLS "network.sts.max_time_for_events_between_two_polls"
@@ -226,6 +226,35 @@ nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler
    return rv;
}

// the number of sockets that can be attached at any given time is
// limited.  this is done because some operating systems (e.g., Win9x)
// limit the number of sockets that can be created by an application.
// AttachSocket will fail if the limit is exceeded.  consumers should
// call CanAttachSocket and check the result before creating a socket.

bool
nsSocketTransportService::CanAttachSocket()
{
    static bool reported900FDLimit = false;
    static bool reported256FDLimit = false;

    uint32_t total = mActiveCount + mIdleCount;
    bool rv = total < gMaxCount;

    if (mTelemetryEnabledPref) {
        if (((total >= 900) || !rv) && !reported900FDLimit) {
            reported900FDLimit = true;
            Telemetry::Accumulate(Telemetry::NETWORK_SESSION_AT_900FD, true);
        }
        if ((total >= 256) && !reported256FDLimit) {
            reported256FDLimit = true;
            Telemetry::Accumulate(Telemetry::NETWORK_SESSION_AT_256FD, true);
        }
    }

    return rv;
}

nsresult
nsSocketTransportService::DetachSocket(SocketContext *listHead, SocketContext *sock)
{
@@ -378,10 +407,12 @@ bool
nsSocketTransportService::GrowActiveList()
{
    int32_t toAdd = gMaxCount - mActiveListSize;
    if (toAdd > 100)
    if (toAdd > 100) {
        toAdd = 100;
    if (toAdd < 1)
    } else if (toAdd < 1) {
        MOZ_ASSERT(false, "CanAttachSocket() should prevent this");
        return false;
    }

    mActiveListSize += toAdd;
    mActiveList = (SocketContext *)
@@ -395,10 +426,12 @@ bool
nsSocketTransportService::GrowIdleList()
{
    int32_t toAdd = gMaxCount - mIdleListSize;
    if (toAdd > 100)
    if (toAdd > 100) {
        toAdd = 100;
    if (toAdd < 1)
    } else if (toAdd < 1) {
        MOZ_ASSERT(false, "CanAttachSocket() should prevent this");
        return false;
    }

    mIdleListSize += toAdd;
    mIdleList = (SocketContext *)
@@ -794,7 +827,7 @@ nsSocketTransportService::Run()
    }
#endif

    SOCKET_LOG(("STS thread init\n"));
    SOCKET_LOG(("STS thread init %d sockets\n", gMaxCount));

    psm::InitializeSSLServerCertVerificationThreads();

@@ -1407,6 +1440,7 @@ nsSocketTransportService::ProbeMaxCount()
        if (pfd[index].fd)
            PR_Close(pfd[index].fd);

    Telemetry::Accumulate(Telemetry::NETWORK_PROBE_MAXCOUNT, gMaxCount);
    SOCKET_LOG(("Socket Limit Test max was confirmed at %d\n", gMaxCount));
}
#endif // windows
@@ -1420,35 +1454,37 @@ nsSocketTransportService::DiscoverMaxCount()
    // On unix and os x network sockets and file
    // descriptors are the same. OS X comes defaulted at 256,
    // most linux at 1000. We can reliably use [sg]rlimit to
    // query that and raise it. We will try to raise it 250 past
    // our target number of SOCKET_LIMIT_TARGET so that some descriptors
    // are still available for other things.
    // query that and raise it if needed.

    struct rlimit rlimitData;
    if (getrlimit(RLIMIT_NOFILE, &rlimitData) == -1)
    if (getrlimit(RLIMIT_NOFILE, &rlimitData) == -1) // rlimit broken - use min
        return PR_SUCCESS;
    if (rlimitData.rlim_cur >=  SOCKET_LIMIT_TARGET + 250) {

    if (rlimitData.rlim_cur >= SOCKET_LIMIT_TARGET) { // larger than target!
        gMaxCount = SOCKET_LIMIT_TARGET;
        return PR_SUCCESS;
    }

    int32_t maxallowed = rlimitData.rlim_max;
    if (maxallowed == -1) {                       /* no limit */
        maxallowed = SOCKET_LIMIT_TARGET + 250;
    } else if ((uint32_t)maxallowed < SOCKET_LIMIT_MIN + 250) {
        return PR_SUCCESS;
    } else if ((uint32_t)maxallowed > SOCKET_LIMIT_TARGET + 250) {
        maxallowed = SOCKET_LIMIT_TARGET + 250;
    if ((uint32_t)maxallowed <= SOCKET_LIMIT_MIN) {
        return PR_SUCCESS; // so small treat as if rlimit is broken
    }

    if ((maxallowed == -1) || // no hard cap - ok to set target
        ((uint32_t)maxallowed >= SOCKET_LIMIT_TARGET)) {
        maxallowed = SOCKET_LIMIT_TARGET;
    }

    rlimitData.rlim_cur = maxallowed;
    setrlimit(RLIMIT_NOFILE, &rlimitData);
    if (getrlimit(RLIMIT_NOFILE, &rlimitData) != -1)
        if (rlimitData.rlim_cur > SOCKET_LIMIT_MIN + 250)
            gMaxCount = rlimitData.rlim_cur - 250;
    if ((getrlimit(RLIMIT_NOFILE, &rlimitData) != -1) &&
        (rlimitData.rlim_cur > SOCKET_LIMIT_MIN)) {
        gMaxCount = rlimitData.rlim_cur;
    }

#elif defined(XP_WIN) && !defined(WIN_CE)
    // >= XP is confirmed to have at least 1000
    PR_STATIC_ASSERT(SOCKET_LIMIT_TARGET <= 1000);
    gMaxCount = SOCKET_LIMIT_TARGET;
#else
    // other platforms are harder to test - so leave at safe legacy value
+1 −10
Original line number Diff line number Diff line
@@ -94,16 +94,7 @@ public:
    static PRCallOnceType gMaxCountInitOnce;
    static PRStatus DiscoverMaxCount();

    //
    // the number of sockets that can be attached at any given time is
    // limited.  this is done because some operating systems (e.g., Win9x)
    // limit the number of sockets that can be created by an application.
    // AttachSocket will fail if the limit is exceeded.  consumers should
    // call CanAttachSocket and check the result before creating a socket.
    //
    bool CanAttachSocket() {
        return mActiveCount + mIdleCount < gMaxCount;
    }
    bool CanAttachSocket();

    // Called by the networking dashboard on the socket thread only
    // Fills the passed array with socket information
+24 −0
Original line number Diff line number Diff line
@@ -2766,6 +2766,30 @@
    "kind": "boolean",
    "description": "session used autodialer"
  },
  "NETWORK_SESSION_AT_256FD": {
    "expires_in_version": "49",
    "kind": "boolean",
    "description": "session exceeded old 256 limit",
    "bug_numbers": [1260218],
    "alert_emails": ["necko@mozilla.com"]
  },
  "NETWORK_SESSION_AT_900FD": {
    "expires_in_version": "never",
    "kind": "boolean",
    "description": "session reached 900 fd limit sockets",
    "bug_numbers": [1260218],
    "alert_emails": ["necko@mozilla.com"]
  },
  "NETWORK_PROBE_MAXCOUNT": {
    "expires_in_version": "never",
    "kind": "linear",
    "low": 50,
    "high": 1000,
    "n_buckets": 10,
    "description": "Result of nsSocketTransportService::ProbeMaxCount()",
    "bug_numbers": [1260218],
    "alert_emails": ["necko@mozilla.com"]
  },
  "FIND_PLUGINS": {
    "alert_emails": ["perf-telemetry-alerts@mozilla.com"],
    "expires_in_version": "never",