diff --git a/ChangeLog b/ChangeLog index 17ad31e3..507eca71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 25/7/14 started 7.40.5 - fix a race in im_maxpos_avg() +- limit n_thr on tiny images 4/7/14 started 7.40.4 - fix vips_rawsave_fd(), thanks aferrero2707 diff --git a/TODO b/TODO index 0475cf41..3c84c9aa 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,4 @@ -- threadpool recyling might be useful for dzsave? - - check and fix up docs diff --git a/libvips/iofuncs/threadpool.c b/libvips/iofuncs/threadpool.c index 00b3f0c1..84b5ebe3 100644 --- a/libvips/iofuncs/threadpool.c +++ b/libvips/iofuncs/threadpool.c @@ -13,6 +13,8 @@ * 17/7/10 * - set pool->error whenever we set thr->error, lets us catch allocate * errors (thanks Tim) + * 25/7/14 + * - limit nthr on tiny images */ /* @@ -688,6 +690,10 @@ static VipsThreadpool * vips_threadpool_new( VipsImage *im ) { VipsThreadpool *pool; + int tile_width; + int tile_height; + int n_tiles; + int n_lines; /* Allocate and init new thread block. */ @@ -705,6 +711,14 @@ vips_threadpool_new( VipsImage *im ) pool->stop = FALSE; pool->done_first = FALSE; + /* If this is a tiny image, we won't need all nthr threads. Guess how + * many tiles we might need to cover the image and use that to limit + * the number of threads we create. + */ + vips_get_tile_size( im, &tile_width, &tile_height, &n_lines ); + n_tiles = (1 + im->Xsize / tile_width) * (1 + im->Ysize / tile_height); + pool->nthr = VIPS_MIN( pool->nthr, n_tiles ); + /* Attach tidy-up callback. */ g_signal_connect( im, "close", @@ -919,7 +933,7 @@ vips_threadpool_run( VipsImage *im, * @im: image to guess for * @tile_width: return selected tile width * @tile_height: return selected tile height - * @nlines: return buffer height in scanlines + * @n_lines: return buffer height in scanlines * * Pick a tile size and a buffer height for this image and the current * value of vips_concurrency_get(). The buffer height @@ -927,7 +941,7 @@ vips_threadpool_run( VipsImage *im, */ void vips_get_tile_size( VipsImage *im, - int *tile_width, int *tile_height, int *nlines ) + int *tile_width, int *tile_height, int *n_lines ) { const int nthr = vips_concurrency_get(); @@ -954,25 +968,25 @@ vips_get_tile_size( VipsImage *im, g_assert( 0 ); } - /* We can't set nlines for the current demand style: a later bit of + /* We can't set n_lines for the current demand style: a later bit of * the pipeline might see a different hint and we need to synchronise * buffer sizes everywhere. * * Pick the maximum buffer size we might possibly need, then round up * to a multiple of tileheight. */ - *nlines = vips__tile_height * + *n_lines = vips__tile_height * (1 + nthr / VIPS_MAX( 1, im->Xsize / vips__tile_width )) * 2; - *nlines = VIPS_MAX( *nlines, vips__fatstrip_height * nthr * 2 ); - *nlines = VIPS_MAX( *nlines, vips__thinstrip_height * nthr * 2 ); - *nlines = ROUND_UP( *nlines, *tile_height ); + *n_lines = VIPS_MAX( *n_lines, vips__fatstrip_height * nthr * 2 ); + *n_lines = VIPS_MAX( *n_lines, vips__thinstrip_height * nthr * 2 ); + *n_lines = ROUND_UP( *n_lines, *tile_height ); /* We make this assumption in several places. */ - g_assert( *nlines % *tile_height == 0 ); + g_assert( *n_lines % *tile_height == 0 ); VIPS_DEBUG_MSG( "vips_get_tile_size: %d by %d patches, " "groups of %d scanlines\n", - *tile_width, *tile_height, *nlines ); + *tile_width, *tile_height, *n_lines ); }