From 09774740a7702e86a35448c9c1941440fe80548a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 22 Feb 2017 20:11:52 +0000 Subject: [PATCH] better cache sizing --- TODO | 17 ----------------- libvips/conversion/tilecache.c | 2 +- libvips/iofuncs/sink.c | 35 +++++++++++++++++++++++++++++++++- libvips/iofuncs/sinkdisc.c | 5 +++++ 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/TODO b/TODO index 88b621f3..40c1ca70 100644 --- a/TODO +++ b/TODO @@ -1,20 +1,3 @@ -- seq no longer stalls ahead threads ... instead, we rely on sinkdisk - interlocks to limit how far ahead or behind threads can get - - reexamine cache sizing ... are they too large? - - is thumbnail thinstrip or fatstrip? how does that affect seq cache sizing? - - add something to linecache (and tilecache?) to get it to display cache size - - sinkdisk could use a smaller wbuffer for thinstrip .. thinstrip * nthreads high - ... this would reduce the size of the input caches we need during shrink - - same for fatstrip ... would it be less than tile-height? - - - - - vips linecache has access there twice! $ vips linecache diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index 14808159..e280961e 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -382,7 +382,7 @@ vips_block_cache_build( VipsObject *object ) build( object ) ) return( -1 ); - VIPS_DEBUG_MSG( "vips_block_cache_build: max size = %g MB\n", + g_info( "vips_block_cache_build: max size = %g MB", (cache->max_tiles * cache->tile_width * cache->tile_height * VIPS_IMAGE_SIZEOF_PEL( cache->in )) / (1024 * 1024.0) ); diff --git a/libvips/iofuncs/sink.c b/libvips/iofuncs/sink.c index e950ffdf..14371ee3 100644 --- a/libvips/iofuncs/sink.c +++ b/libvips/iofuncs/sink.c @@ -200,6 +200,9 @@ sink_free( Sink *sink ) void vips_sink_base_init( SinkBase *sink_base, VipsImage *image ) { + int tiles_across; + int tiles_down; + /* Always clear kill before we start looping. See the * call to vips_image_iskilled() below. */ @@ -208,12 +211,42 @@ vips_sink_base_init( SinkBase *sink_base, VipsImage *image ) sink_base->im = image; sink_base->x = 0; sink_base->y = 0; + sink_base->processed = 0; vips_get_tile_size( image, &sink_base->tile_width, &sink_base->tile_height, &sink_base->nlines ); - sink_base->processed = 0; + /* vips_get_tile_size() is very conservative about setting nlines. We + * know that we are the final element in the pipeline, so we can be + * much tighter. + */ + + /* Number of tiles we need across to fill the image width. This will be + * 1 for fat/thin strip. + */ + tiles_across = + VIPS_ROUND_UP( image->Xsize, sink_base->tile_width ) / + sink_base->tile_width; + + /* Number of rows of tiles we need to have at least 1 tile per thread. + */ + tiles_down = + VIPS_ROUND_UP( vips_concurrency_get(), tiles_across ) / + tiles_across; + + /* Therefore the number of scanlines to have at least one tile per + * thread in a buffer. + */ + sink_base->nlines = tiles_down * sink_base->tile_height; + + g_info( _( "%s %s: %d x %d pixels, %d threads, %d x %d tiles, " + "%d lines in buffer" ), + g_get_prgname(), image->filename, + image->Xsize, image->Ysize, + vips_concurrency_get(), + sink_base->tile_width, sink_base->tile_height, + sink_base->nlines ); } static int diff --git a/libvips/iofuncs/sinkdisc.c b/libvips/iofuncs/sinkdisc.c index 30f2134b..36483ae3 100644 --- a/libvips/iofuncs/sinkdisc.c +++ b/libvips/iofuncs/sinkdisc.c @@ -238,6 +238,11 @@ wbuffer_new( Write *write ) return( NULL ); } + g_info( "wbuffer_new: %g MB", + (write->sink_base.nlines * + VIPS_IMAGE_SIZEOF_LINE( write->sink_base.im )) / + (1024 * 1024.0) ); + return( wbuffer ); }