From 36e0b60ffaec26587b47b23fc6ddc065341b45bf Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 22 Mar 2016 14:35:44 +0000 Subject: [PATCH] put the resize cache back again stops overcomputation on vips_shrink() --- libvips/iofuncs/image.c | 6 ++++-- libvips/resample/resize.c | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 4a3bd3d2..41e10f50 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -490,8 +490,10 @@ vips_image_dispose( GObject *gobject ) int compute_percent = 100.0 * pixels->npels / pixels->tpels; if( compute_percent > 100 ) - printf( "vips_image_dispose: %s computed %d%%\n", - pixels->nickname, compute_percent ); + printf( "vips_image_dispose: %s %s computed %d%%\n", + image->filename, + pixels->nickname, + compute_percent ); } } #endif /*DEBUG_LEAK*/ diff --git a/libvips/resample/resize.c b/libvips/resample/resize.c index b77b587c..8cea30dd 100644 --- a/libvips/resample/resize.c +++ b/libvips/resample/resize.c @@ -150,6 +150,51 @@ vips_resize_build( VipsObject *object ) hresidual = (double) target_width / in->Xsize; vresidual = (double) target_height / in->Ysize; + /* We will get overcomputation on vips_shrink() from the vips_reduce() + * coming later, so read into a cache where tiles are scanlines, and + * make sure we keep enough scanlines. + * + * We use a threaded tilecache to avoid a deadlock: suppose thread1, + * evaluating the top block of the output, is delayed, and thread2, + * evaluating the second block, gets here first (this can happen on + * a heavily-loaded system). + * + * With an unthreaded tilecache, thread2 will get + * the cache lock and start evaling the second block of the shrink. + * When it reaches the png reader it will stall until the first block + * has been used ... but it never will, since thread1 will block on + * this cache lock. + * + * Cache sizing: we double-buffer writes, so threads can be up to one + * line of tiles behind. For example, one thread could be allocated + * tile (0,0) and then stall, the whole write system won't stall until + * it tries to allocate tile (0, 2). + * + * We reduce down after this, which can be a scale of up to @residual, + * perhaps 0.5 or down as low as 0.3. So the number of scanlines we + * need to keep for the worst case is 2 * @tile_height / @residual, + * plus a little extra. + */ + if( int_vshrink > 1 ) { + int tile_width; + int tile_height; + int n_lines; + int need_lines; + + vips_get_tile_size( in, + &tile_width, &tile_height, &n_lines ); + need_lines = 1.2 * n_lines / vresidual; + if( vips_tilecache( in, &t[6], + "tile_width", in->Xsize, + "tile_height", 10, + "max_tiles", 1 + need_lines / 10, + "access", VIPS_ACCESS_SEQUENTIAL, + "threaded", TRUE, + NULL ) ) + return( -1 ); + in = t[6]; + } + /* Any downsizing. */ if( hresidual < 1.0 ||