Changeset 5172


Ignore:
Timestamp:
Feb 29, 2008, 3:41:50 AM (15 years ago)
Author:
charles
Message:

use a custom struct for the peer's four request queues since John_Clay's shark report shows it taking up about 40% of the time in malloc/free. also, maybe this will help the "idle memory" numbers some.

Location:
trunk/libtransmission
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/ipcparse.c

    r5143 r5172  
    309309{
    310310    tr_benc pk;
    311     uint8_t  * ret;
    312 
    313     if( NULL == ipc_initval( info, id, tag, &pk, TYPE_STR ) )
    314         return NULL;
    315 
    316     ret = ipc_mkval( &pk, len );
    317     SAFEBENCFREE( &pk );
     311    uint8_t  * ret = NULL;
     312
     313    if( ipc_initval( info, id, tag, &pk, TYPE_STR ) )
     314    {
     315        ret = ipc_mkval( &pk, len );
     316        SAFEBENCFREE( &pk );
     317    }
    318318
    319319    return ret;
     
    325325{
    326326    tr_benc pk, * val;
    327     uint8_t  * ret;
    328 
    329     val = ipc_initval( info, id, tag, &pk, TYPE_INT );
    330     if( !val )
    331         return NULL;
    332 
    333     val->val.i = num;
    334     ret = ipc_mkval( &pk, len );
    335     SAFEBENCFREE( &pk );
     327    uint8_t  * ret = NULL;
     328
     329    if(( val = ipc_initval( info, id, tag, &pk, TYPE_INT )))
     330    {
     331        val->val.i = num;
     332        ret = ipc_mkval( &pk, len );
     333        SAFEBENCFREE( &pk );
     334    }
    336335
    337336    return ret;
     
    343342{
    344343    tr_benc pk, * val;
    345     uint8_t  * ret;
    346 
    347     val = ipc_initval( info, id, tag, &pk, TYPE_STR );
    348     if( !val )
    349         return NULL;
    350 
    351     tr_bencInitStr( val, str, -1, 1 );
    352     ret = ipc_mkval( &pk, len );
    353     SAFEBENCFREE( &pk );
     344    uint8_t  * ret = NULL;
     345
     346    if(( val = ipc_initval( info, id, tag, &pk, TYPE_STR )))
     347    {
     348        tr_bencInitStr( val, str, -1, 1 );
     349        ret = ipc_mkval( &pk, len );
     350        SAFEBENCFREE( &pk );
     351    }
    354352
    355353    return ret;
  • trunk/libtransmission/peer-msgs.c

    r5127 r5172  
    2424#include "completion.h"
    2525#include "inout.h"
    26 #include "list.h"
    2726#include "peer-io.h"
    2827#include "peer-mgr.h"
     
    7170    RATE_PULSE_INTERVAL     = (250),       /* msec between calls to ratePulse() */
    7271
     72    MAX_QUEUE_SIZE          = (100),
     73
    7374    MAX_OUTBUF_SIZE         = (1024),
    7475     
     
    8081
    8182    SENT_REQUEST_TTL_SECS = 90
    82 
    8383};
    8484
     
    111111}
    112112
     113struct request_list
     114{
     115    uint16_t count;
     116    uint16_t max;
     117    struct peer_request * requests;
     118};
     119
     120static const struct request_list REQUEST_LIST_INIT = { 0, 0, NULL };
     121
     122static void
     123reqListReserve( struct request_list * list, uint16_t max )
     124{
     125    if( list->max < max )
     126    {
     127        list->max = max;
     128        list->requests = tr_renew( struct peer_request, list->requests, list->max );
     129    }
     130}
     131
     132static void
     133reqListClear( struct request_list * list )
     134{
     135    tr_free( list->requests );
     136    *list = REQUEST_LIST_INIT;
     137}
     138
     139static void
     140reqListRemoveOne( struct request_list * list, int i )
     141{
     142    assert( 0<=i && i<list->count );
     143
     144    memmove( &list->requests[i],
     145             &list->requests[i+1],
     146             sizeof( struct peer_request ) * ( --list->count - i ) );
     147}
     148
     149static void
     150reqListAppend( struct request_list * list, const struct peer_request * req )
     151{
     152    if( ++list->count >= list->max )
     153        reqListReserve( list, list->max + 8 );
     154
     155    list->requests[list->count-1] = *req;
     156}
     157
     158static tr_errno
     159reqListPop( struct request_list * list, struct peer_request * setme )
     160{
     161    tr_errno err;
     162
     163    if( !list->count )
     164        err = TR_ERROR;
     165    else {
     166        *setme = list->requests[0];
     167        reqListRemoveOne( list, 0 );
     168        err = TR_OK;
     169    }
     170
     171    return err;
     172}
     173
     174static int
     175reqListFind( struct request_list * list, const struct peer_request * key )
     176{
     177    uint16_t i;
     178    for( i=0; i<list->count; ++i )
     179        if( !compareRequest( key, list->requests+i ) )
     180            return i;
     181    return -1;
     182}
     183
     184static tr_errno
     185reqListRemove( struct request_list * list, const struct peer_request * key )
     186{
     187    tr_errno err;
     188    const int i = reqListFind( list, key );
     189
     190    if( i < 0 )
     191        err = TR_ERROR;
     192    else {
     193        err = TR_OK;
     194        reqListRemoveOne( list, i );
     195    }
     196
     197    return err;
     198}
     199
     200static void
     201reqListPrune( struct request_list * list,
     202              struct request_list * pruned,
     203              time_t                cutoff )
     204{
     205    int i, k=0, p=0;
     206    struct peer_request keep[MAX_QUEUE_SIZE];
     207    struct peer_request prune[MAX_QUEUE_SIZE];
     208
     209    for( i=0; i<list->count; ++i ) {
     210        const struct peer_request * req = list->requests + i;
     211        if( req->time_requested > cutoff )
     212            keep[k++] = *req;
     213        else
     214            prune[p++] = *req;
     215    }
     216
     217    memcpy( list->requests, keep, sizeof(struct peer_request) * k );
     218    list->count = k;
     219
     220    reqListReserve( pruned, pruned->count + p );
     221    memcpy( pruned->requests + pruned->count, prune, sizeof(struct peer_request) * p );
     222    pruned->count += p;
     223}
     224
    113225/* this is raw, unchanged data from the peer regarding
    114226 * the current message that it's sending us. */
     
    133245    struct evbuffer * outBlock;    /* buffer of all the current piece message */
    134246    struct evbuffer * outMessages; /* buffer of all the non-piece messages */
    135     tr_list * peerAskedFor;
    136     tr_list * peerAskedForFast;
    137     tr_list * clientAskedFor;
    138     tr_list * clientWillAskFor;
     247    struct request_list peerAskedFor;
     248    struct request_list peerAskedForFast;
     249    struct request_list clientAskedFor;
     250    struct request_list clientWillAskFor;
    139251
    140252    tr_timer * rateTimer;
     
    414526cancelAllRequestsToClientExceptFast( tr_peermsgs * msgs )
    415527{
    416     tr_list_free( &msgs->peerAskedFor, tr_free );
     528    reqListClear( &msgs->peerAskedFor );
    417529}
    418530
     
    584696expireOldRequests( tr_peermsgs * msgs )
    585697{
    586     tr_list * l;
    587     tr_list * prune = NULL;
     698    int i;
    588699    const time_t now = time( NULL );
    589 
    590     /* find queued requests that are too old
    591        "time_requested" here is when the request was queued */
    592     for( l=msgs->clientWillAskFor; l!=NULL; l=l->next ) {
    593         struct peer_request * req = l->data;
    594         if( req->time_requested + QUEUED_REQUEST_TTL_SECS < now )
    595             tr_list_prepend( &prune, req );
    596     }
    597 
    598     /* find sent requests that are too old
    599        "time_requested" here is when the request was sent */
    600     for( l=msgs->clientAskedFor; l!=NULL; l=l->next ) {
    601         struct peer_request * req = l->data;
    602         if( req->time_requested + SENT_REQUEST_TTL_SECS < now )
    603             tr_list_prepend( &prune, req );
    604     }
     700    const time_t queued_cutoff = now - QUEUED_REQUEST_TTL_SECS;
     701    const time_t sent_cutoff   = now - SENT_REQUEST_TTL_SECS;
     702    struct request_list pruned = REQUEST_LIST_INIT;
     703
     704    reqListPrune( &msgs->clientWillAskFor, &pruned, queued_cutoff );
     705    reqListPrune( &msgs->clientAskedFor, &pruned, sent_cutoff );
    605706
    606707    /* expire the old requests */
    607     for( l=prune; l!=NULL; l=l->next ) {
    608         struct peer_request * req = l->data;
     708    for( i=0; i<pruned.count; ++i ) {
     709        const struct peer_request * req = &pruned.requests[i];
    609710        tr_peerMsgsCancel( msgs, req->index, req->offset, req->length );
    610711    }
    611712
    612713    /* cleanup */
    613     tr_list_free( &prune, NULL );
     714    reqListClear( &pruned );
    614715}
    615716
     
    617718pumpRequestQueue( tr_peermsgs * msgs )
    618719{
     720    struct peer_request req;
    619721    const int max = msgs->maxActiveRequests;
    620722    const int min = msgs->minActiveRequests;
    621     int count = tr_list_size( msgs->clientAskedFor );
     723    const time_t now = time( NULL );
     724    int count = msgs->clientAskedFor.count;
    622725    int sent = 0;
    623726
     
    627730        return;
    628731
    629     while( ( count < max ) && ( msgs->clientWillAskFor != NULL ) )
    630     {
    631         struct peer_request * r = tr_list_pop_front( &msgs->clientWillAskFor );
    632         assert( requestIsValid( msgs, r ) );
    633         assert( tr_bitfieldHas( msgs->info->have, r->index ) );
    634         protocolSendRequest( msgs, r );
    635         r->time_requested = msgs->lastReqAddedAt = time( NULL );
    636         tr_list_append( &msgs->clientAskedFor, r );
     732    while( ( count < max ) && !reqListPop( &msgs->clientWillAskFor, &req ) )
     733    {
     734        assert( requestIsValid( msgs, &req ) );
     735        assert( tr_bitfieldHas( msgs->info->have, req.index ) );
     736
     737        protocolSendRequest( msgs, &req );
     738        req.time_requested = msgs->lastReqAddedAt = now;
     739        reqListAppend( &msgs->clientAskedFor, &req );
     740
    637741        ++count;
    638742        ++sent;
     
    642746        dbgmsg( msgs, "pump sent %d requests, now have %d active and %d queued",
    643747                sent,
    644                 tr_list_size(msgs->clientAskedFor),
    645                 tr_list_size(msgs->clientWillAskFor) );
     748                msgs->clientAskedFor.count,
     749                msgs->clientWillAskFor.count );
    646750
    647751    if( count < max )
     
    659763{
    660764    const int req_max = msgs->maxActiveRequests;
    661     struct peer_request tmp, *req;
     765    struct peer_request req;
    662766
    663767    assert( msgs != NULL );
     
    680784
    681785    /* peer's queue is full */
    682     if( tr_list_size( msgs->clientWillAskFor ) >= req_max ) {
     786    if( msgs->clientWillAskFor.count >= req_max ) {
    683787        dbgmsg( msgs, "declining request because we're full" );
    684788        return TR_ADDREQ_FULL;
     
    686790
    687791    /* have we already asked for this piece? */
    688     tmp.index = index;
    689     tmp.offset = offset;
    690     tmp.length = length;
    691     if( tr_list_find( msgs->clientAskedFor, &tmp, compareRequest ) ) {
     792    req.index = index;
     793    req.offset = offset;
     794    req.length = length;
     795    if( reqListFind( &msgs->clientAskedFor, &req ) != -1 ) {
    692796        dbgmsg( msgs, "declining because it's a duplicate" );
    693797        return TR_ADDREQ_DUPLICATE;
    694798    }
    695     if( tr_list_find( msgs->clientWillAskFor, &tmp, compareRequest ) ) {
     799    if( reqListFind( &msgs->clientWillAskFor, &req ) != -1 ) {
    696800        dbgmsg( msgs, "declining because it's a duplicate" );
    697801        return TR_ADDREQ_DUPLICATE;
     
    703807
    704808    dbgmsg( msgs, "added req for piece %d, offset %d", (int)index, (int)offset );
    705     req = tr_new0( struct peer_request, 1 );
    706     *req = tmp;
    707     req->time_requested = time( NULL );
    708     tr_list_append( &msgs->clientWillAskFor, req );
     809    req.time_requested = time( NULL );
     810    reqListAppend( &msgs->clientWillAskFor, &req );
    709811    return TR_ADDREQ_OK;
    710812}
     
    713815cancelAllRequestsToPeer( tr_peermsgs * msgs )
    714816{
    715     struct peer_request * req;
    716 
    717     while(( req = tr_list_pop_front( &msgs->clientWillAskFor ) ))
    718     {
    719         fireCancelledReq( msgs, req );
    720         tr_free( req );
    721     }
    722 
    723     while(( req = tr_list_pop_front( &msgs->clientAskedFor ) ))
    724     {
    725         fireCancelledReq( msgs, req );
    726         protocolSendCancel( msgs, req );
    727         tr_free( req );
    728     }
     817    int i;
     818    struct request_list a = msgs->clientWillAskFor;
     819    struct request_list b = msgs->clientAskedFor;
     820
     821    msgs->clientAskedFor = REQUEST_LIST_INIT;
     822    msgs->clientWillAskFor = REQUEST_LIST_INIT;
     823
     824    for( i=0; i<a.count; ++i )
     825        fireCancelledReq( msgs, &a.requests[i] );
     826
     827    for( i=0; i<b.count; ++i ) {
     828        fireCancelledReq( msgs, &b.requests[i] );
     829        protocolSendCancel( msgs, &b.requests[i] );
     830    }
     831
     832    reqListClear( &a );
     833    reqListClear( &b );
    729834}
    730835
     
    735840                   uint32_t      length )
    736841{
    737     struct peer_request *req, tmp;
     842    struct peer_request req;
    738843
    739844    assert( msgs != NULL );
     
    741846
    742847    /* have we asked the peer for this piece? */
    743     tmp.index = pieceIndex;
    744     tmp.offset = offset;
    745     tmp.length = length;
     848    req.index = pieceIndex;
     849    req.offset = offset;
     850    req.length = length;
    746851
    747852    /* if it's only in the queue and hasn't been sent yet, free it */
    748     if(( req = tr_list_remove( &msgs->clientWillAskFor, &tmp, compareRequest ) ))
    749     {
    750         fireCancelledReq( msgs, req );
    751         tr_free( req );
    752     }
     853    if( !reqListRemove( &msgs->clientWillAskFor, &req ) )
     854        fireCancelledReq( msgs, &req );
    753855
    754856    /* if it's already been sent, send a cancel message too */
    755     if(( req = tr_list_remove( &msgs->clientAskedFor, &tmp, compareRequest ) ))
    756     {
    757         protocolSendCancel( msgs, req );
    758         fireCancelledReq( msgs, req );
    759         tr_free( req );
     857    if( !reqListRemove( &msgs->clientAskedFor, &req ) ) {
     858        protocolSendCancel( msgs, &req );
     859        fireCancelledReq( msgs, &req );
    760860    }
    761861}
     
    10321132    else /* YAY */
    10331133    {
    1034         struct peer_request * tmp = tr_new( struct peer_request, 1 );
    1035         *tmp = *req;
    10361134        if( peerIsFast && pieceIsFast )
    1037             tr_list_append( &msgs->peerAskedForFast, tmp );
     1135            reqListAppend( &msgs->peerAskedForFast, req );
    10381136        else
    1039             tr_list_append( &msgs->peerAskedFor, tmp );
     1137            reqListAppend( &msgs->peerAskedFor, req );
    10401138    }
    10411139}
     
    12401338            tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
    12411339            dbgmsg( msgs, "got a Cancel %u:%u->%u", req.index, req.offset, req.length );
    1242             tr_free( tr_list_remove( &msgs->peerAskedForFast, &req, compareRequest ) );
    1243             tr_free( tr_list_remove( &msgs->peerAskedFor, &req, compareRequest ) );
     1340            reqListRemove( &msgs->peerAskedForFast, &req );
     1341            reqListRemove( &msgs->peerAskedFor, &req );
    12441342            break;
    12451343        }
     
    12841382            tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
    12851383            tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
    1286             tr_free( tr_list_remove( &msgs->clientAskedFor, &req, compareRequest ) );
     1384            reqListRemove( &msgs->clientAskedFor, &req );
    12871385            break;
    12881386        }
     
    13911489    tr_torrent * tor = msgs->torrent;
    13921490    const int block = _tr_block( tor, req->index, req->offset );
    1393     struct peer_request *myreq;
    13941491
    13951492    assert( msgs != NULL );
     
    14101507    **/
    14111508
    1412     myreq = tr_list_remove( &msgs->clientAskedFor, req, compareRequest );
    1413     if( myreq == NULL ) {
     1509    if( reqListRemove( &msgs->clientAskedFor, req ) )
     1510    {
    14141511        clientGotUnwantedBlock( msgs, req );
    14151512        dbgmsg( msgs, "we didn't ask for this message..." );
     
    14171514    }
    14181515
    1419     dbgmsg( msgs, "got block %u:%u->%u (turnaround time %d secs)",
    1420                   myreq->index, myreq->offset, myreq->length,
    1421                   (int)(time(NULL) - myreq->time_requested) );
    14221516    dbgmsg( msgs, "peer has %d more blocks we've asked for",
    1423                   tr_list_size(msgs->clientAskedFor));
    1424 
    1425     tr_free( myreq );
    1426     myreq = NULL;
     1517                  msgs->clientAskedFor.count );
    14271518
    14281519    /**
     
    15561647    msgs->info->rateToClient = tr_rcRate( msgs->info->rcToClient );
    15571648    msgs->info->rateToPeer = tr_rcRate( msgs->info->rcToPeer );
    1558     msgs->maxActiveRequests = MIN( 4 + (int)(msgs->info->rateToClient/4), 100 );
     1649    msgs->maxActiveRequests = MIN( 4 + (int)(msgs->info->rateToClient/4), MAX_QUEUE_SIZE );
    15591650    msgs->minActiveRequests = msgs->maxActiveRequests / 3;
    15601651    return TRUE;
    15611652}
    15621653
    1563 static struct peer_request*
    1564 popNextRequest( tr_peermsgs * msgs )
    1565 {
    1566     struct peer_request * ret;
    1567     ret = tr_list_pop_front( &msgs->peerAskedForFast );
    1568     if( !ret )
    1569         ret = tr_list_pop_front( &msgs->peerAskedFor);
    1570     return ret;
     1654static tr_errno
     1655popNextRequest( tr_peermsgs * msgs, struct peer_request * setme )
     1656{
     1657    if( !reqListPop( &msgs->peerAskedForFast, setme ) )
     1658        return 0;
     1659    if( !reqListPop( &msgs->peerAskedFor, setme ) )
     1660        return 0;
     1661
     1662    return TR_ERROR;
    15711663}
    15721664
     
    15761668    const time_t now = time( NULL );
    15771669    tr_peermsgs * msgs = vmsgs;
    1578     struct peer_request * r;
    15791670
    15801671    tr_peerIoTryRead( msgs->io );
     
    16071698    if( !msgs->sendingBlock )
    16081699    {
     1700        struct peer_request req;
     1701
    16091702        if(( EVBUFFER_LENGTH( msgs->outMessages ) ))
    16101703        {
     
    16141707        }
    16151708        else if( !EVBUFFER_LENGTH( msgs->outBlock )
    1616             && (( r = popNextRequest( msgs )))
    1617             && requestIsValid( msgs, r )
    1618             && tr_cpPieceIsComplete( msgs->torrent->completion, r->index ) )
     1709            && !popNextRequest( msgs, &req )
     1710            && requestIsValid( msgs, &req )
     1711            && tr_cpPieceIsComplete( msgs->torrent->completion, req.index ) )
    16191712        {
    1620             uint8_t * buf = tr_new( uint8_t, r->length );
    1621 
    1622             if( !tr_ioRead( msgs->torrent, r->index, r->offset, r->length, buf ) )
     1713            uint8_t * buf = tr_new( uint8_t, req.length );
     1714
     1715            if( !tr_ioRead( msgs->torrent, req.index, req.offset, req.length, buf ) )
    16231716            {
    16241717                tr_peerIo * io = msgs->io;
    16251718                struct evbuffer * out = msgs->outBlock;
    16261719
    1627                 dbgmsg( msgs, "sending block %u:%u->%u", r->index, r->offset, r->length );
    1628                 tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + r->length );
     1720                dbgmsg( msgs, "sending block %u:%u->%u", req.index, req.offset, req.length );
     1721                tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + req.length );
    16291722                tr_peerIoWriteUint8 ( io, out, BT_PIECE );
    1630                 tr_peerIoWriteUint32( io, out, r->index );
    1631                 tr_peerIoWriteUint32( io, out, r->offset );
    1632                 tr_peerIoWriteBytes ( io, out, buf, r->length );
     1723                tr_peerIoWriteUint32( io, out, req.index );
     1724                tr_peerIoWriteUint32( io, out, req.offset );
     1725                tr_peerIoWriteBytes ( io, out, buf, req.length );
    16331726                msgs->sendingBlock = 1;
    16341727            }
    16351728
    16361729            tr_free( buf );
    1637             tr_free( r );
    16381730        }
    16391731        else if( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS )
     
    18511943    m->outBlock = evbuffer_new( );
    18521944    m->peerAllowedPieces = NULL;
     1945    m->peerAskedFor = REQUEST_LIST_INIT;
     1946    m->peerAskedForFast = REQUEST_LIST_INIT;
     1947    m->clientAskedFor = REQUEST_LIST_INIT;
     1948    m->clientWillAskFor = REQUEST_LIST_INIT;
    18531949    m->clientAllowedPieces = tr_bitfieldNew( m->torrent->info.pieceCount );
    18541950    m->clientSuggestedPieces = tr_bitfieldNew( m->torrent->info.pieceCount );
     
    18891985        tr_timerFree( &msgs->pexTimer );
    18901986        tr_publisherFree( &msgs->publisher );
    1891         tr_list_free( &msgs->clientWillAskFor, tr_free );
    1892         tr_list_free( &msgs->clientAskedFor, tr_free );
    1893         tr_list_free( &msgs->peerAskedForFast, tr_free );
    1894         tr_list_free( &msgs->peerAskedFor, tr_free );
     1987        reqListClear( &msgs->clientWillAskFor );
     1988        reqListClear( &msgs->clientAskedFor );
     1989        reqListClear( &msgs->peerAskedForFast );
     1990        reqListClear( &msgs->peerAskedFor );
    18951991        tr_bitfieldFree( msgs->peerAllowedPieces );
    18961992        tr_bitfieldFree( msgs->clientAllowedPieces );
Note: See TracChangeset for help on using the changeset viewer.