diff --git a/libtransmission/makemeta.c b/libtransmission/makemeta.c index 0ff178532..16908d041 100644 --- a/libtransmission/makemeta.c +++ b/libtransmission/makemeta.c @@ -8,6 +8,7 @@ * the Transmission project. */ +#include #include #include #include @@ -73,22 +74,39 @@ getFiles( const char * dir, } static int -bestPieceSize( uint64_t totalSize ) +bestPieceSize( uint64_t totalSize, uint64_t fileCount ) { - const int MiB = 1048576; - const int GiB = totalSize / (uint64_t)1073741824; + int pieceSize = 1; + const int minPieceSize = 65536; /* arbitrary; 2^16 */ + const int maxPieceSize = 16777216; /* arbitrary; 2^24 */ + const int desiredMinPiecesPerFile = 15; /* arbitrary */ + uint64_t log; - /* almost always best to have a piee size of 512 or 256 kb. - common practice seems to be to bump up to 1MB pieces at - at total size of around 8GiB or so */ + /* start off in the range of (1024..2048] pieces + for "normal" torrents... */ + log = totalSize; + while( log > 2048 ) { + log >>= 1; + pieceSize <<= 1; + } - if( GiB >= 8 ) - return MiB; + /* special case 1: torrents with a lot of small files. + try to have a reasonable number of pieces per file, + which will reduce overhead on selective downloading + and increase swarm speed. */ + while( totalSize/pieceSize < (fileCount * desiredMinPiecesPerFile) ) { + const int swap = pieceSize >> 1; + if( swap < minPieceSize ) + break; + pieceSize = swap; + } - if( GiB >= 1 ) - return MiB / 2; + /* special case 2: enormous single-file torrents. our normal + case creates unwieldly piece sizes in that case */ + while( pieceSize < maxPieceSize ) + pieceSize >>= 1; - return MiB / 4; + return pieceSize; } static int @@ -148,7 +166,7 @@ tr_metaInfoBuilderCreate( tr_handle_t * handle, const char * topFile ) sizeof(tr_metainfo_builder_file_t), builderFileCompare ); - ret->pieceSize = bestPieceSize( ret->totalSize ); + ret->pieceSize = bestPieceSize( ret->totalSize, ret->fileCount ); ret->pieceCount = (int)( ret->totalSize / ret->pieceSize); if( ret->totalSize % ret->pieceSize ) ++ret->pieceCount;