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() - python .bandrank() now works like .bandjoin()
- vipsthumbnail --interpolator and --sharpen switches are deprecated - vipsthumbnail --interpolator and --sharpen switches are deprecated
- switches to disable PPM, Rad and Analyze support - switches to disable PPM, Rad and Analyze support
- added VIPS_COUNT_PIXELS(), overcomputation tracking
27/1/16 started 8.2.3 27/1/16 started 8.2.3
- fix a crash with SPARC byte-order labq vips images - 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 - if we do
vips_region_prepare( VipsRect { 0, 0, 100, 10 } ) 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 do we recalculate the whole region, or shift the calculated bits down and
just fetch another line? 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 ); 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 #ifdef __cplusplus
} }
#endif /*__cplusplus*/ #endif /*__cplusplus*/

View File

@ -125,6 +125,19 @@ void vips_region_invalidate( VipsRegion *reg );
void vips_region_dump_all( void ); 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. /* Macros on VipsRegion.
* VIPS_REGION_LSKIP() add to move down line * VIPS_REGION_LSKIP() add to move down line
* VIPS_REGION_N_ELEMENTS() number of elements across region * 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 ); 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 ) ); vips_object_preclose( VIPS_OBJECT( gobject ) );
/* We have to junk the fd in dispose, since we run this for rewind and /* 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->sizeof_header = VIPS_SIZEOF_HEADER;
image->mode = g_strdup( "p" ); 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 int

View File

@ -102,6 +102,12 @@ static char *vips__argv0 = NULL;
*/ */
int vips__leak = 0; 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: * vips_get_argv0:
* *
@ -394,6 +400,11 @@ vips_init( const char *argv0 )
atexit( vips_shutdown ); atexit( vips_shutdown );
#endif /*HAVE_ATEXIT*/ #endif /*HAVE_ATEXIT*/
#ifdef DEBUG_LEAK
vips__image_pixels_quark =
g_quark_from_static_string( "vips-image-pixels" );
#endif /*DEBUG_LEAK*/
done = TRUE; done = TRUE;
vips__thread_gate_stop( "init: startup" ); vips__thread_gate_stop( "init: startup" );

View File

@ -1631,3 +1631,21 @@ vips_region_dump_all( void )
g_mutex_unlock( vips__global_lock ); g_mutex_unlock( vips__global_lock );
} }
#endif /*VIPS_DEBUG*/ #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_GATE_STOP( "vips_affine_gen: work" );
VIPS_COUNT_PIXELS( or, "vips_affine_gen" );
return( 0 ); return( 0 );
} }

View File

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

View File

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

View File

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

View File

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