Changeset 10865


Ignore:
Timestamp:
Jun 26, 2010, 4:21:50 PM (12 years ago)
Author:
charles
Message:

(trunk libT) #1521 "memory cache to reduce disk IO" -- improved average flush size thanks to efficiency patch from sadface

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/cache.c

    r10798 r10865  
    3333    uint32_t length;
    3434
     35    time_t time;
    3536    tr_block_index_t block;
    3637
     
    5455****/
    5556
     57struct run_info
     58{
     59  time_t  last_block_time;
     60  tr_bool is_aligned;
     61};
     62
     63
    5664/* return a count of how many contiguous blocks there are starting at this pos */
    5765static int
    58 getBlockRun( const tr_cache * cache, int pos )
     66getBlockRun( const tr_cache * cache, int pos, struct run_info * info )
    5967{
    6068    int i;
     
    6876        if( b->block != block ) break;
    6977        if( b->tor != ref->tor ) break;
    70 //fprintf( stderr, "pos %d tor %d block %zu\n", i, b->tor->uniqueId, (size_t)b->block );
     78//fprintf( stderr, "pos %d tor %d block %zu time %zu\n", i, b->tor->uniqueId, (size_t)b->block, (size_t)b->time );
    7179    }
    7280
    7381//fprintf( stderr, "run is %d long from [%d to %d)\n", (int)(i-pos), i, (int)pos );
     82    if( info != NULL ) {
     83        info->last_block_time = blocks[i-1]->time;
     84        info->is_aligned = (blocks[pos]->block % 2 == 0) ? TRUE : FALSE;
     85    }
     86
    7487    return i-pos;
    7588}
    7689
    77 /* return the starting index of the longest contiguous run of blocks */
    78 static int
    79 findLargestChunk( tr_cache * cache, int * setme_n )
     90/* return the starting index of the longest contiguous run of blocks BUT:
     91 *   1 - Length of run must be even.
     92 *   2 - Run must begin with a even block.
     93 *   3 - Oldest run is preferred.
     94 */
     95static int
     96findChunk2Discard( tr_cache * cache, int * setme_n )
    8097{
    8198    const int n = tr_ptrArraySize( &cache->blocks );
    8299    int pos;
    83100    int bestpos = 0;
    84     int bestlen = getBlockRun( cache, bestpos );
    85 
    86     for( pos=bestlen; pos<n; )
    87     {
    88         const int len = getBlockRun( cache, pos );
     101    unsigned bestlen = 1;
     102    unsigned jump;
     103    time_t oldest_time = ~0;
     104    struct run_info run;
     105
     106    for( pos=0; pos<n; pos+=jump )
     107    {
     108        unsigned len = getBlockRun( cache, pos, &run );
     109        jump = len;
     110
     111        /* shortcut */
     112        if( len < bestlen )
     113            continue;
     114
     115        /* check alignment */
     116        if( len % 2 == 0 ) {
     117            if( !run.is_aligned )
     118                /* Let it grow. Otherwise we contribute to fragmentation */
     119                continue;
     120        } else {
     121            if( len != 1 ) {
     122                --len;
     123                if( !run.is_aligned ) {
     124                    ++pos;
     125                    --jump;
     126                }
     127            }
     128        }
    89129
    90130        if( bestlen < len ) {
    91131            bestlen = len;
    92132            bestpos = pos;
     133            oldest_time = run.last_block_time;
     134        } else if( (bestlen == len) && (oldest_time > run.last_block_time) ) {
     135            bestpos = pos;
     136            oldest_time = run.last_block_time;
    93137        }
    94 
    95         pos += len;
    96     }
    97 
    98 //fprintf( stderr, "LONGEST run is %d long from [%d to %d)\n", bestlen, bestpos, bestpos+bestlen );
     138    }
     139
     140//fprintf( stderr, "DISCARDED run is %d long from [%d to %d)\n", bestlen, bestpos, bestpos+bestlen );
    99141    *setme_n = bestlen;
    100142    return bestpos;
     
    147189    {
    148190        int n;
    149         const int i = findLargestChunk( cache, &n );
     191        const int i = findChunk2Discard( cache, &n );
    150192        err = flushContiguous( cache, i, n );
    151193    }
     
    159201
    160202static int
    161 getMaxBlocks( size_t maxMiB )
    162 {
    163     const double maxBytes = maxMiB * 1024 * 1024;
     203getMaxBlocks( double maxMiB )
     204{
     205    const double maxBytes = maxMiB * (1024 * 1024);
    164206    return maxBytes / MAX_BLOCK_SIZE;
    165207}
     
    183225tr_cacheNew( double maxMiB )
    184226{
    185     tr_cache * cache = tr_new( tr_cache, 1 );
     227    tr_cache * cache = tr_new0( tr_cache, 1 );
    186228    cache->blocks = TR_PTR_ARRAY_INIT;
    187229    cache->maxBlocks = getMaxBlocks( maxMiB );
     
    215257        return a->block < b->block ? -1 : 1;
    216258
    217     if( a->block < b->block ) return -1;
    218     if( a->block > b->block ) return  1;
    219 
    220     /* they'r eequal */
     259    /* they're equal */
    221260    return 0;
    222261}
     
    256295    }
    257296
     297    cb->time = tr_time();
     298
    258299    tr_free( cb->buf );
    259300    cb->buf = tr_memdup( writeme, cb->length );
     
    329370        if( b->tor != torrent ) break;
    330371        if( ( b->block < begin ) || ( b->block >= end ) ) break;
    331         err = flushContiguous( cache, pos, getBlockRun( cache, pos ) );
     372        err = flushContiguous( cache, pos, getBlockRun( cache, pos, NULL ) );
    332373    }
    333374
     
    346387        const struct cache_block * b = tr_ptrArrayNth( &cache->blocks, pos );
    347388        if( b->tor != torrent ) break;
    348         err = flushContiguous( cache, pos, getBlockRun( cache, pos ) );
    349     }
    350 
    351     return err;
    352 }
     389        err = flushContiguous( cache, pos, getBlockRun( cache, pos, NULL ) );
     390    }
     391
     392    return err;
     393}
Note: See TracChangeset for help on using the changeset viewer.