From 88b2f4350d7e3e46b55a53c6cafc1e3d81009d47 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 20 Nov 2013 14:46:46 +0000 Subject: [PATCH] better cache sizing in unbuffered sequential mode Previously we only ever had a single tile of cache in unbuffered mode. This could break with many threads, if thread requests crossed tile boundaries. Now have one tile per thread, plus a bit for slop. --- ChangeLog | 3 +++ configure.ac | 6 +++--- libvips/conversion/sequential.c | 17 +++++++++-------- libvips/conversion/tilecache.c | 7 ++++++- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 56dd5aab..c61a1cce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +20/11/13 started 7.36.5 +- better cache sizing in unbuffered sequential mode + 15/11/13 started 7.36.4 - improve compat with im_init_world() diff --git a/configure.ac b/configure.ac index 581d70c3..ea2ed891 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # also update the version number in the m4 macros below -AC_INIT([vips], [7.36.4], [vipsip@jiscmail.ac.uk]) +AC_INIT([vips], [7.36.5], [vipsip@jiscmail.ac.uk]) # required for gobject-introspection AC_PREREQ(2.62) @@ -17,7 +17,7 @@ AC_CONFIG_MACRO_DIR([m4]) # user-visible library versioning m4_define([vips_major_version], [7]) m4_define([vips_minor_version], [36]) -m4_define([vips_micro_version], [4]) +m4_define([vips_micro_version], [5]) m4_define([vips_version], [vips_major_version.vips_minor_version.vips_micro_version]) @@ -37,7 +37,7 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date` # binary interface changes not backwards compatible?: reset age to 0 LIBRARY_CURRENT=35 -LIBRARY_REVISION=4 +LIBRARY_REVISION=5 LIBRARY_AGE=0 # patched into include/vips/version.h diff --git a/libvips/conversion/sequential.c b/libvips/conversion/sequential.c index d5b473f5..3b361804 100644 --- a/libvips/conversion/sequential.c +++ b/libvips/conversion/sequential.c @@ -46,6 +46,7 @@ */ /* +#define VIPS_DEBUG_GREEN #define VIPS_DEBUG */ @@ -120,7 +121,7 @@ vips_sequential_generate( VipsRegion *or, VipsRect *r = &or->valid; VipsRegion *ir = (VipsRegion *) seq; - VIPS_DEBUG_MSG( "thread %p request for line %d, height %d\n", + VIPS_DEBUG_MSG_GREEN( "thread %p request for line %d, height %d\n", g_thread_self(), r->top, r->height ); if( sequential->trace ) @@ -130,7 +131,7 @@ vips_sequential_generate( VipsRegion *or, g_mutex_lock( sequential->lock ); - VIPS_DEBUG_MSG( "thread %p has lock ...\n", g_thread_self() ); + VIPS_DEBUG_MSG_GREEN( "thread %p has lock ...\n", g_thread_self() ); /* If we've seen an error, everything must stop. */ @@ -163,7 +164,7 @@ vips_sequential_generate( VipsRegion *or, g_time_val_add( &time, STALL_TIME * 1000000 ); #endif - VIPS_DEBUG_MSG( "thread %p stalling for up to %gs ...\n", + VIPS_DEBUG_MSG_GREEN( "thread %p stalling for up to %gs ...\n", g_thread_self(), STALL_TIME ); /* Exit the loop on timeout or condition passes. We have to @@ -180,7 +181,7 @@ vips_sequential_generate( VipsRegion *or, break; #endif - VIPS_DEBUG_MSG( "thread %p awake again ...\n", + VIPS_DEBUG_MSG_GREEN( "thread %p awake again ...\n", g_thread_self() ); } @@ -194,7 +195,7 @@ vips_sequential_generate( VipsRegion *or, */ VipsRect area; - VIPS_DEBUG_MSG( "thread %p skipping to line %d ...\n", + VIPS_DEBUG_MSG_GREEN( "thread %p skipping to line %d ...\n", g_thread_self(), r->top ); @@ -217,7 +218,7 @@ vips_sequential_generate( VipsRegion *or, /* This is a request for old or present pixels -- serve from cache. * This may trigger further, sequential reads. */ - VIPS_DEBUG_MSG( "thread %p reading ...\n", g_thread_self() ); + VIPS_DEBUG_MSG_GREEN( "thread %p reading ...\n", g_thread_self() ); if( vips_region_prepare( ir, r ) || vips_region_region( or, ir, r, r->left, r->top ) ) { VIPS_DEBUG_MSG( "thread %p error, unlocking ...\n", @@ -234,7 +235,7 @@ vips_sequential_generate( VipsRegion *or, */ sequential->y_pos = VIPS_RECT_BOTTOM( r ); - VIPS_DEBUG_MSG( "thread %p updating y_pos to %d and " + VIPS_DEBUG_MSG_GREEN( "thread %p updating y_pos to %d and " "waking stalled\n", g_thread_self(), sequential->y_pos ); @@ -242,7 +243,7 @@ vips_sequential_generate( VipsRegion *or, g_cond_broadcast( sequential->ready ); } - VIPS_DEBUG_MSG( "thread %p unlocking ...\n", g_thread_self() ); + VIPS_DEBUG_MSG_GREEN( "thread %p unlocking ...\n", g_thread_self() ); g_mutex_unlock( sequential->lock ); diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index 52c63c2b..a3837089 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -899,7 +899,12 @@ vips_line_cache_build( VipsObject *object ) block_cache->access = cache->access; if( cache->access == VIPS_ACCESS_SEQUENTIAL_UNBUFFERED ) - block_cache->max_tiles = 1; + /* A tile per thread. + * + * Imagine scanline tiles and four threads. And add a bit for + * slop. + */ + block_cache->max_tiles = 2 * vips_concurrency_get(); else { /* Enough lines for two complete buffers would be exactly * right. Make it 3 to give us some slop room.