add VIPS_COUNT_PIXELS, overcomputation tracking

added VIPS_COUNT_PIXELS(), use like this:

	static int vips_shrinkh_gen( VipsRegion *or, ... )
	{
        	VIPS_COUNT_PIXELS( or, "vips_shrinkh_gen" );
	}

and on image close, if more than 100% of the pixels have been
calculated, you get a warning

only if you enable debugging, since this hurts perf slightly
This commit is contained in:
John Cupitt 2016-03-22 12:26:45 +00:00
parent 4f8aca3a93
commit e8b5cb6c23
12 changed files with 106 additions and 4 deletions

View File

@ -19,6 +19,7 @@
- python .bandrank() now works like .bandjoin()
- vipsthumbnail --interpolator and --sharpen switches are deprecated
- switches to disable PPM, Rad and Analyze support
- added VIPS_COUNT_PIXELS(), overcomputation tracking
27/1/16 started 8.2.3
- fix a crash with SPARC byte-order labq vips images

21
TODO
View File

@ -1,7 +1,3 @@
- could instrument vips_region_prepare() and track number of pixels calculated
for each image ... on image close (or evelend?) print %computed, values over
100% would indicate overcomputation
- if we do
vips_region_prepare( VipsRect { 0, 0, 100, 10 } )
@ -10,6 +6,23 @@
do we recalculate the whole region, or shift the calculated bits down and
just fetch another line?
how would we calculate a small part of a region?
vips_region_fill() would need to do this
instrument a bit and see what kinds of buffers we are seeing
if we see
buffer.done: true
buffer.area: {0, 0, 100, 10 }
and we are asked for
buffer.area: {0, 1, 100, 10 }
we can scroll, then use vips_region_prepare_to() to calculate just the
new pixels ... would this fix it?

View File

@ -233,6 +233,19 @@ char *vips__make_xml_metadata( const char *domain, VipsImage *image );
void vips__cairo2rgba( guint32 *buf, int n );
#ifdef DEBUG_LEAK
extern GQuark vips__image_pixels_quark;
#endif /*DEBUG_LEAK*/
/* With DEBUG_LEAK, hang one of these off each image and count pixels
* calculated.
*/
typedef struct _VipsImagePixels {
const char *nickname;
gint64 tpels; /* Number of pels we expect to calculate */
gint64 npels; /* Number of pels calculated so far */
} VipsImagePixels;
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -125,6 +125,19 @@ void vips_region_invalidate( VipsRegion *reg );
void vips_region_dump_all( void );
#ifdef DEBUG_LEAK
void vips__region_count_pixels( VipsRegion *region, const char *nickname );
#endif /*DEBUG_LEAK*/
/* Use this to count pixels passing through key points. Handy for spotting bad
* overcomputation.
*/
#ifdef DEBUG_LEAK
#define VIPS_COUNT_PIXELS( R, N ) vips__region_count_pixels( R, N )
#else /*!DEBUG_LEAK*/
#define VIPS_COUNT_PIXELS( R, N )
#endif /*DEBUG_LEAK*/
/* Macros on VipsRegion.
* VIPS_REGION_LSKIP() add to move down line
* VIPS_REGION_N_ELEMENTS() number of elements across region

View File

@ -480,6 +480,22 @@ vips_image_dispose( GObject *gobject )
VIPS_DEBUG_MSG( "vips_image_dispose: %p\n", gobject );
#ifdef DEBUG_LEAK
{
VipsImagePixels *pixels = g_object_get_qdata( G_OBJECT( image ),
vips__image_pixels_quark );
if( pixels &&
pixels->tpels ) {
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 );
}
}
#endif /*DEBUG_LEAK*/
vips_object_preclose( VIPS_OBJECT( gobject ) );
/* We have to junk the fd in dispose, since we run this for rewind and
@ -1368,6 +1384,11 @@ vips_image_init( VipsImage *image )
image->sizeof_header = VIPS_SIZEOF_HEADER;
image->mode = g_strdup( "p" );
#ifdef DEBUG_LEAK
g_object_set_qdata_full( G_OBJECT( image ), vips__image_pixels_quark,
g_new0( VipsImagePixels, 1 ), (GDestroyNotify) g_free );
#endif /*DEBUG_LEAK*/
}
int

View File

@ -102,6 +102,12 @@ static char *vips__argv0 = NULL;
*/
int vips__leak = 0;
#ifdef DEBUG_LEAK
/* Count pixels processed per image here.
*/
GQuark vips__image_pixels_quark = 0;
#endif /*DEBUG_LEAK*/
/**
* vips_get_argv0:
*
@ -394,6 +400,11 @@ vips_init( const char *argv0 )
atexit( vips_shutdown );
#endif /*HAVE_ATEXIT*/
#ifdef DEBUG_LEAK
vips__image_pixels_quark =
g_quark_from_static_string( "vips-image-pixels" );
#endif /*DEBUG_LEAK*/
done = TRUE;
vips__thread_gate_stop( "init: startup" );

View File

@ -1631,3 +1631,21 @@ vips_region_dump_all( void )
g_mutex_unlock( vips__global_lock );
}
#endif /*VIPS_DEBUG*/
#ifdef DEBUG_LEAK
void
vips__region_count_pixels( VipsRegion *region, const char *nickname )
{
VipsImage *image = region->im;
VipsImagePixels *pixels = g_object_get_qdata( G_OBJECT( image ),
vips__image_pixels_quark );
g_mutex_lock( vips__global_lock );
if( !pixels->tpels )
pixels->tpels = VIPS_IMAGE_N_PELS( image );
if( !pixels->nickname )
pixels->nickname = nickname;
pixels->npels += region->valid.width * region->valid.height;
g_mutex_unlock( vips__global_lock );
}
#endif /*DEBUG_LEAK*/

View File

@ -367,6 +367,8 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
VIPS_GATE_STOP( "vips_affine_gen: work" );
VIPS_COUNT_PIXELS( or, "vips_affine_gen" );
return( 0 );
}

View File

@ -399,6 +399,8 @@ vips_reduceh_gen( VipsRegion *out_region, void *seq,
VIPS_GATE_STOP( "vips_reduceh_gen: work" );
VIPS_COUNT_PIXELS( out_region, "vips_reduceh_gen" );
return( 0 );
}

View File

@ -591,6 +591,8 @@ vips_reducev_gen( VipsRegion *out_region, void *vseq,
VIPS_GATE_STOP( "vips_reducev_gen: work" );
VIPS_COUNT_PIXELS( out_region, "vips_reducev_gen" );
return( 0 );
}
@ -666,6 +668,8 @@ vips_reducev_vector_gen( VipsRegion *out_region, void *vseq,
VIPS_GATE_STOP( "vips_reducev_vector_gen: work" );
VIPS_COUNT_PIXELS( out_region, "vips_reducev_vector_gen" );
return( 0 );
}

View File

@ -218,6 +218,8 @@ vips_shrinkh_gen( VipsRegion *or, void *seq,
VIPS_GATE_STOP( "vips_shrinkh_gen: work" );
}
VIPS_COUNT_PIXELS( or, "vips_shrinkh_gen" );
return( 0 );
}

View File

@ -316,6 +316,8 @@ vips_shrinkv_gen( VipsRegion *or, void *vseq,
VIPS_GATE_STOP( "vips_shrinkv_gen: work" );
}
VIPS_COUNT_PIXELS( or, "vips_shrinkv_gen" );
return( 0 );
}