mirror of
https://github.com/transmission/transmission
synced 2025-03-04 10:38:13 +00:00
(trunk libT) avoid some unnecessary memory fragmentation... for composited objects that have a tr_bitfield, contain it directly rather than a pointer to one allocated elsewhere on the heap.
This commit is contained in:
parent
427f639664
commit
7a4002dd3a
5 changed files with 54 additions and 42 deletions
|
@ -38,10 +38,10 @@ struct tr_completion
|
||||||
tr_torrent * tor;
|
tr_torrent * tor;
|
||||||
|
|
||||||
/* do we have this block? */
|
/* do we have this block? */
|
||||||
tr_bitfield * blockBitfield;
|
tr_bitfield blockBitfield;
|
||||||
|
|
||||||
/* do we have this piece? */
|
/* do we have this piece? */
|
||||||
tr_bitfield * pieceBitfield;
|
tr_bitfield pieceBitfield;
|
||||||
|
|
||||||
/* a block is complete if and only if we have it */
|
/* a block is complete if and only if we have it */
|
||||||
uint16_t * completeBlocks;
|
uint16_t * completeBlocks;
|
||||||
|
@ -63,8 +63,8 @@ struct tr_completion
|
||||||
static void
|
static void
|
||||||
tr_cpReset( tr_completion * cp )
|
tr_cpReset( tr_completion * cp )
|
||||||
{
|
{
|
||||||
tr_bitfieldClear( cp->pieceBitfield );
|
tr_bitfieldClear( &cp->pieceBitfield );
|
||||||
tr_bitfieldClear( cp->blockBitfield );
|
tr_bitfieldClear( &cp->blockBitfield );
|
||||||
memset( cp->completeBlocks, 0,
|
memset( cp->completeBlocks, 0,
|
||||||
sizeof( uint16_t ) * cp->tor->info.pieceCount );
|
sizeof( uint16_t ) * cp->tor->info.pieceCount );
|
||||||
cp->sizeNow = 0;
|
cp->sizeNow = 0;
|
||||||
|
@ -78,9 +78,9 @@ tr_cpInit( tr_torrent * tor )
|
||||||
tr_completion * cp = tr_new( tr_completion, 1 );
|
tr_completion * cp = tr_new( tr_completion, 1 );
|
||||||
|
|
||||||
cp->tor = tor;
|
cp->tor = tor;
|
||||||
cp->blockBitfield = tr_bitfieldNew( tor->blockCount );
|
|
||||||
cp->pieceBitfield = tr_bitfieldNew( tor->info.pieceCount );
|
|
||||||
cp->completeBlocks = tr_new( uint16_t, tor->info.pieceCount );
|
cp->completeBlocks = tr_new( uint16_t, tor->info.pieceCount );
|
||||||
|
tr_bitfieldConstruct( &cp->blockBitfield, tor->blockCount );
|
||||||
|
tr_bitfieldConstruct( &cp->pieceBitfield, tor->info.pieceCount );
|
||||||
tr_cpReset( cp );
|
tr_cpReset( cp );
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,9 @@ tr_cpInit( tr_torrent * tor )
|
||||||
void
|
void
|
||||||
tr_cpClose( tr_completion * cp )
|
tr_cpClose( tr_completion * cp )
|
||||||
{
|
{
|
||||||
tr_free ( cp->completeBlocks );
|
tr_free( cp->completeBlocks );
|
||||||
tr_bitfieldFree( cp->pieceBitfield );
|
tr_bitfieldDestruct( &cp->pieceBitfield );
|
||||||
tr_bitfieldFree( cp->blockBitfield );
|
tr_bitfieldDestruct( &cp->blockBitfield );
|
||||||
tr_free ( cp );
|
tr_free ( cp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ tr_cpPieceIsComplete( const tr_completion * cp,
|
||||||
const tr_bitfield *
|
const tr_bitfield *
|
||||||
tr_cpPieceBitfield( const tr_completion * cp )
|
tr_cpPieceBitfield( const tr_completion * cp )
|
||||||
{
|
{
|
||||||
return cp->pieceBitfield;
|
return &cp->pieceBitfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -193,15 +193,15 @@ tr_cpPieceRem( tr_completion * cp,
|
||||||
cp->sizeWhenDoneIsDirty = 1;
|
cp->sizeWhenDoneIsDirty = 1;
|
||||||
cp->haveValidIsDirty = 1;
|
cp->haveValidIsDirty = 1;
|
||||||
cp->completeBlocks[piece] = 0;
|
cp->completeBlocks[piece] = 0;
|
||||||
tr_bitfieldRemRange ( cp->blockBitfield, start, end );
|
tr_bitfieldRemRange ( &cp->blockBitfield, start, end );
|
||||||
tr_bitfieldRem( cp->pieceBitfield, piece );
|
tr_bitfieldRem( &cp->pieceBitfield, piece );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tr_cpBlockIsComplete( const tr_completion * cp,
|
tr_cpBlockIsComplete( const tr_completion * cp,
|
||||||
tr_block_index_t block )
|
tr_block_index_t block )
|
||||||
{
|
{
|
||||||
return tr_bitfieldHas( cp->blockBitfield, block );
|
return tr_bitfieldHas( &cp->blockBitfield, block );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -219,9 +219,9 @@ tr_cpBlockAdd( tr_completion * cp,
|
||||||
++cp->completeBlocks[piece];
|
++cp->completeBlocks[piece];
|
||||||
|
|
||||||
if( tr_cpPieceIsComplete( cp, piece ) )
|
if( tr_cpPieceIsComplete( cp, piece ) )
|
||||||
tr_bitfieldAdd( cp->pieceBitfield, piece );
|
tr_bitfieldAdd( &cp->pieceBitfield, piece );
|
||||||
|
|
||||||
tr_bitfieldAdd( cp->blockBitfield, block );
|
tr_bitfieldAdd( &cp->blockBitfield, block );
|
||||||
|
|
||||||
cp->sizeNow += blockSize;
|
cp->sizeNow += blockSize;
|
||||||
|
|
||||||
|
@ -234,11 +234,10 @@ const tr_bitfield *
|
||||||
tr_cpBlockBitfield( const tr_completion * cp )
|
tr_cpBlockBitfield( const tr_completion * cp )
|
||||||
{
|
{
|
||||||
assert( cp );
|
assert( cp );
|
||||||
assert( cp->blockBitfield );
|
assert( cp->blockBitfield.bits );
|
||||||
assert( cp->blockBitfield->bits );
|
assert( cp->blockBitfield.bitCount );
|
||||||
assert( cp->blockBitfield->bitCount );
|
|
||||||
|
|
||||||
return cp->blockBitfield;
|
return &cp->blockBitfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -249,7 +248,6 @@ tr_cpBlockBitfieldSet( tr_completion * cp,
|
||||||
|
|
||||||
assert( cp );
|
assert( cp );
|
||||||
assert( bitfield );
|
assert( bitfield );
|
||||||
assert( cp->blockBitfield );
|
|
||||||
|
|
||||||
if( tr_bitfieldTestFast( bitfield, cp->tor->blockCount - 1 ) )
|
if( tr_bitfieldTestFast( bitfield, cp->tor->blockCount - 1 ) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -537,7 +537,7 @@ torrentRealInit( tr_session * session,
|
||||||
|
|
||||||
tor->error = 0;
|
tor->error = 0;
|
||||||
|
|
||||||
tor->checkedPieces = tr_bitfieldNew( tor->info.pieceCount );
|
tr_bitfieldConstruct( &tor->checkedPieces, tor->info.pieceCount );
|
||||||
tr_torrentUncheck( tor );
|
tr_torrentUncheck( tor );
|
||||||
|
|
||||||
tor->addedDate = time( NULL ); /* this is a default value to be
|
tor->addedDate = time( NULL ); /* this is a default value to be
|
||||||
|
@ -1063,7 +1063,7 @@ freeTorrent( tr_torrent * tor )
|
||||||
tr_trackerFree( tor->tracker );
|
tr_trackerFree( tor->tracker );
|
||||||
tor->tracker = NULL;
|
tor->tracker = NULL;
|
||||||
|
|
||||||
tr_bitfieldFree( tor->checkedPieces );
|
tr_bitfieldDestruct( &tor->checkedPieces );
|
||||||
|
|
||||||
tr_free( tor->downloadDir );
|
tr_free( tor->downloadDir );
|
||||||
tr_free( tor->peer_id );
|
tr_free( tor->peer_id );
|
||||||
|
@ -1601,7 +1601,7 @@ tr_bool
|
||||||
tr_torrentIsPieceChecked( const tr_torrent * tor,
|
tr_torrentIsPieceChecked( const tr_torrent * tor,
|
||||||
tr_piece_index_t piece )
|
tr_piece_index_t piece )
|
||||||
{
|
{
|
||||||
return tr_bitfieldHas( tor->checkedPieces, piece );
|
return tr_bitfieldHas( &tor->checkedPieces, piece );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1610,9 +1610,9 @@ tr_torrentSetPieceChecked( tr_torrent * tor,
|
||||||
tr_bool isChecked )
|
tr_bool isChecked )
|
||||||
{
|
{
|
||||||
if( isChecked )
|
if( isChecked )
|
||||||
tr_bitfieldAdd( tor->checkedPieces, piece );
|
tr_bitfieldAdd( &tor->checkedPieces, piece );
|
||||||
else
|
else
|
||||||
tr_bitfieldRem( tor->checkedPieces, piece );
|
tr_bitfieldRem( &tor->checkedPieces, piece );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1625,9 +1625,9 @@ tr_torrentSetFileChecked( tr_torrent * tor,
|
||||||
const tr_piece_index_t end = file->lastPiece + 1;
|
const tr_piece_index_t end = file->lastPiece + 1;
|
||||||
|
|
||||||
if( isChecked )
|
if( isChecked )
|
||||||
tr_bitfieldAddRange ( tor->checkedPieces, begin, end );
|
tr_bitfieldAddRange ( &tor->checkedPieces, begin, end );
|
||||||
else
|
else
|
||||||
tr_bitfieldRemRange ( tor->checkedPieces, begin, end );
|
tr_bitfieldRemRange ( &tor->checkedPieces, begin, end );
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_bool
|
tr_bool
|
||||||
|
@ -1650,14 +1650,13 @@ tr_torrentIsFileChecked( const tr_torrent * tor,
|
||||||
void
|
void
|
||||||
tr_torrentUncheck( tr_torrent * tor )
|
tr_torrentUncheck( tr_torrent * tor )
|
||||||
{
|
{
|
||||||
tr_bitfieldRemRange ( tor->checkedPieces, 0, tor->info.pieceCount );
|
tr_bitfieldRemRange ( &tor->checkedPieces, 0, tor->info.pieceCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tr_torrentCountUncheckedPieces( const tr_torrent * tor )
|
tr_torrentCountUncheckedPieces( const tr_torrent * tor )
|
||||||
{
|
{
|
||||||
return tor->info.pieceCount - tr_bitfieldCountTrueBits(
|
return tor->info.pieceCount - tr_bitfieldCountTrueBits( &tor->checkedPieces );
|
||||||
tor->checkedPieces );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t*
|
time_t*
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#error only libtransmission should #include this header.
|
#error only libtransmission should #include this header.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "utils.h" /* tr_bitfield */
|
||||||
|
|
||||||
#ifndef TR_TORRENT_H
|
#ifndef TR_TORRENT_H
|
||||||
#define TR_TORRENT_H 1
|
#define TR_TORRENT_H 1
|
||||||
|
|
||||||
|
@ -205,7 +207,7 @@ struct tr_torrent
|
||||||
|
|
||||||
struct tr_completion * completion;
|
struct tr_completion * completion;
|
||||||
|
|
||||||
struct tr_bitfield * checkedPieces;
|
struct tr_bitfield checkedPieces;
|
||||||
tr_completeness completeness;
|
tr_completeness completeness;
|
||||||
|
|
||||||
struct tr_tracker * tracker;
|
struct tr_tracker * tracker;
|
||||||
|
|
|
@ -745,15 +745,25 @@ tr_strstrip( char * str )
|
||||||
*****
|
*****
|
||||||
****/
|
****/
|
||||||
|
|
||||||
|
tr_bitfield*
|
||||||
|
tr_bitfieldConstruct( tr_bitfield * b, size_t bitCount )
|
||||||
|
{
|
||||||
|
b->bitCount = bitCount;
|
||||||
|
b->byteCount = ( bitCount + 7u ) / 8u;
|
||||||
|
b->bits = tr_new0( uint8_t, b->byteCount );
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tr_bitfieldDestruct( tr_bitfield * b )
|
||||||
|
{
|
||||||
|
tr_free( b->bits );
|
||||||
|
}
|
||||||
|
|
||||||
tr_bitfield*
|
tr_bitfield*
|
||||||
tr_bitfieldNew( size_t bitCount )
|
tr_bitfieldNew( size_t bitCount )
|
||||||
{
|
{
|
||||||
tr_bitfield * ret = tr_new0( tr_bitfield, 1 );
|
return tr_bitfieldConstruct( tr_new0( tr_bitfield, 1 ), bitCount );
|
||||||
|
|
||||||
ret->bitCount = bitCount;
|
|
||||||
ret->byteCount = ( bitCount + 7u ) / 8u;
|
|
||||||
ret->bits = tr_new0( uint8_t, ret->byteCount );
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_bitfield*
|
tr_bitfield*
|
||||||
|
@ -772,7 +782,7 @@ tr_bitfieldFree( tr_bitfield * bitfield )
|
||||||
{
|
{
|
||||||
if( bitfield )
|
if( bitfield )
|
||||||
{
|
{
|
||||||
tr_free( bitfield->bits );
|
tr_bitfieldDestruct( bitfield );
|
||||||
tr_free( bitfield );
|
tr_free( bitfield );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,14 +299,17 @@ int tr_httpParseURL( const char * url,
|
||||||
****
|
****
|
||||||
***/
|
***/
|
||||||
|
|
||||||
struct tr_bitfield
|
typedef struct tr_bitfield
|
||||||
{
|
{
|
||||||
uint8_t * bits;
|
uint8_t * bits;
|
||||||
size_t bitCount;
|
size_t bitCount;
|
||||||
size_t byteCount;
|
size_t byteCount;
|
||||||
};
|
}
|
||||||
|
tr_bitfield;
|
||||||
|
|
||||||
typedef struct tr_bitfield tr_bitfield;
|
tr_bitfield* tr_bitfieldConstruct( tr_bitfield*, size_t bitcount );
|
||||||
|
|
||||||
|
void tr_bitfieldDestruct( tr_bitfield* );
|
||||||
|
|
||||||
tr_bitfield* tr_bitfieldNew( size_t bitcount ) TR_GNUC_MALLOC;
|
tr_bitfield* tr_bitfieldNew( size_t bitcount ) TR_GNUC_MALLOC;
|
||||||
|
|
||||||
|
@ -346,7 +349,7 @@ tr_bitfield* tr_bitfieldOr( tr_bitfield*,
|
||||||
need to call tr_bitfieldTestFast() first before you
|
need to call tr_bitfieldTestFast() first before you
|
||||||
start looping. */
|
start looping. */
|
||||||
#define tr_bitfieldHasFast( bitfield, nth ) \
|
#define tr_bitfieldHasFast( bitfield, nth ) \
|
||||||
( ( bitfield->bits[( nth ) >> 3u] << ( ( nth ) & 7u ) & 0x80 ) != 0 )
|
( ( (bitfield)->bits[( nth ) >> 3u] << ( ( nth ) & 7u ) & 0x80 ) != 0 )
|
||||||
|
|
||||||
/** @param high the highest nth bit you're going to access */
|
/** @param high the highest nth bit you're going to access */
|
||||||
#define tr_bitfieldTestFast( bitfield, high ) \
|
#define tr_bitfieldTestFast( bitfield, high ) \
|
||||||
|
|
Loading…
Add table
Reference in a new issue