Ticket #5282: randomized-fetch-order.patch

File randomized-fetch-order.patch, 4.6 KB (added by mikeperry, 7 years ago)

Patch by Martin Henze

  • nsHttpConnectionMgr.cpp

    a b  
    9494{
    9595    LOG(("Creating nsHttpConnectionMgr @%x\n", this));
    9696    mCT.Init();
     97    nsresult rv;
     98    mRandomGenerator = do_GetService("@mozilla.org/security/random-generator;1", &rv);
     99    if (NS_FAILED(rv)) {
     100        mRandomGenerator = nsnull;
     101    }   
    97102}
    98103
    99104nsHttpConnectionMgr::~nsHttpConnectionMgr()
     
    342347        nsConnectionEntry *ent = mCT.Get(ci->HashKey());
    343348        if (ent) {
    344349            // search for another request to pipeline...
    345             PRInt32 i, count = ent->mPendingQ.Length();
     350            PRInt32 i, h, count = ent->mPendingQ.Length();
     351            PRInt32 ind[count];
     352           
    346353            for (i=0; i<count; ++i) {
     354                ind[i] = i;
     355            }
     356           
     357            for (i=0; i < count; ++i) {
     358                PRInt32 r = rand() % count;
     359                PRInt32 temp = ind[i];
     360                ind[i] = ind[r];
     361                ind[r] = temp;
     362            }       
     363       
     364            for (h=0; h<count; ++h) {
     365                i = ind[h];
    347366                nsHttpTransaction *trans = ent->mPendingQ[i];
    348367                if (trans->Caps() & NS_HTTP_ALLOW_PIPELINING) {
    349368                    pipeline->AddTransaction(trans);
     
    585604    LOG(("nsHttpConnectionMgr::ProcessPendingQForEntry [ci=%s]\n",
    586605        ent->mConnInfo->HashKey().get()));
    587606
    588     PRInt32 i, count = ent->mPendingQ.Length();
     607    PRInt32 h, i, count = ent->mPendingQ.Length();
    589608    if (count > 0) {
    590609        LOG(("  pending-count=%u\n", count));
    591610        nsHttpTransaction *trans = nsnull;
    592611        nsHttpConnection *conn = nsnull;
     612       
     613        PRInt32 ind[count];
     614       
    593615        for (i=0; i<count; ++i) {
     616            ind[i] = i;
     617        }
     618       
     619        for (i=0; i < count; ++i) {
     620            PRInt32 r = rand() % count;
     621            PRInt32 temp = ind[i];
     622            ind[i] = ind[r];
     623            ind[r] = temp;
     624        }       
     625       
     626        for (h=0; h<count; ++h) {
     627            i = ind[h];
    594628            trans = ent->mPendingQ[i];
    595629
    596630            // When this transaction has already established a half-open
     
    856890    nsHttpPipeline *pipeline = nsnull;
    857891    if (conn->SupportsPipelining() && (caps & NS_HTTP_ALLOW_PIPELINING)) {
    858892        LOG(("  looking to build pipeline...\n"));
    859         if (BuildPipeline(ent, trans, &pipeline))
     893        if (BuildRandomizedPipeline(ent, trans, &pipeline))
    860894            trans = pipeline;
    861895    }
    862896
     
    929963    return PR_TRUE;
    930964}
    931965
     966PRBool
     967nsHttpConnectionMgr::BuildRandomizedPipeline(nsConnectionEntry *ent,
     968                                   nsAHttpTransaction *firstTrans,
     969                                   nsHttpPipeline **result)
     970{
     971    if (mRandomGenerator == nsnull)
     972        return BuildPipeline(ent, firstTrans, result);
     973    if (mMaxPipelinedRequests < 2)
     974        return PR_FALSE;
     975
     976    nsresult rv;
     977    PRUint8 *bytes = nsnull;
     978
     979    nsHttpPipeline *pipeline = nsnull;
     980    nsHttpTransaction *trans;
     981
     982    PRUint32 i = 0, numAdded = 0, numAllowed = 0;
     983    PRUint32 max = 0;
     984
     985    while (i < ent->mPendingQ.Length()) {
     986        if (ent->mPendingQ[i]->Caps() & NS_HTTP_ALLOW_PIPELINING)
     987            numAllowed++;
     988        i++;
     989    }
     990
     991    rv = mRandomGenerator->GenerateRandomBytes(1, &bytes);
     992    NS_ENSURE_SUCCESS(rv, rv);
     993    // 4...12
     994    max = 4 + (bytes[0] % (mMaxPipelinedRequests + 1));
     995    NS_Free(bytes);
     996
     997    while (numAllowed > 0) {
     998        rv = mRandomGenerator->GenerateRandomBytes(1, &bytes);
     999        NS_ENSURE_SUCCESS(rv, rv);
     1000        i = bytes[0] % ent->mPendingQ.Length();
     1001        NS_Free(bytes);
     1002
     1003        trans = ent->mPendingQ[i];
     1004
     1005        if (!(ent->mPendingQ[i]->Caps() & NS_HTTP_ALLOW_PIPELINING))
     1006            continue;
     1007
     1008        if (numAdded == 0) {
     1009            pipeline = new nsHttpPipeline;
     1010            if (!pipeline)
     1011                return PR_FALSE;
     1012            pipeline->AddTransaction(firstTrans);
     1013            numAdded = 1;
     1014        }
     1015        pipeline->AddTransaction(trans);
     1016
     1017        // remove transaction from pending queue
     1018        ent->mPendingQ.RemoveElementAt(i);
     1019        NS_RELEASE(trans);
     1020
     1021        numAllowed--;
     1022
     1023        if (++numAdded == max)
     1024            break;
     1025    }
     1026
     1027    //fprintf(stderr, "Yay!!! pipelined %u/%u transactions\n", numAdded, max);
     1028    LOG(("  pipelined %u/%u transactions\n", numAdded, max));
     1029
     1030    if (numAdded == 0)
     1031        return PR_FALSE;
     1032
     1033    NS_ADDREF(*result = pipeline);
     1034    return PR_TRUE;
     1035}
     1036
    9321037nsresult
    9331038nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
    9341039{