From 466f25cf28e0bc2ad91141f1da925d7d3e209857 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 9 Dec 2013 10:04:24 +0000 Subject: [PATCH] added memory logging to --vips-profile though the analysis program doesn't understand yet --- libvips/include/vips/gate.h | 14 ++++++++ libvips/iofuncs/gate.c | 67 +++++++++++++++++++++++++++---------- libvips/iofuncs/memory.c | 4 +++ 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/libvips/include/vips/gate.h b/libvips/include/vips/gate.h index afd1e62d..182c0bed 100644 --- a/libvips/include/vips/gate.h +++ b/libvips/include/vips/gate.h @@ -49,6 +49,18 @@ G_STMT_START { \ vips__thread_gate_stop( NAME ); \ } G_STMT_END +#define VIPS_GATE_MALLOC( SIZE ) \ +G_STMT_START { \ + if( vips__thread_profile ) \ + vips__thread_malloc_free( (gint64) (SIZE) ); \ +} G_STMT_END + +#define VIPS_GATE_FREE( SIZE ) \ +G_STMT_START { \ + if( vips__thread_profile ) \ + vips__thread_malloc_free( -((gint64) (SIZE)) ); \ +} G_STMT_END + extern gboolean vips__thread_profile; void vips__thread_profile_attach( const char *thread_name ); @@ -58,6 +70,8 @@ void vips__thread_profile_stop( void ); void vips__thread_gate_start( const char *gate_name ); void vips__thread_gate_stop( const char *gate_name ); +void vips__thread_malloc_free( gint64 size ); + #endif /*VIPS_GATE_H*/ #ifdef __cplusplus diff --git a/libvips/iofuncs/gate.c b/libvips/iofuncs/gate.c index 9b150b39..8cd219bc 100644 --- a/libvips/iofuncs/gate.c +++ b/libvips/iofuncs/gate.c @@ -71,6 +71,7 @@ typedef struct _VipsThreadProfile { const char *name; GThread *thread; GHashTable *gates; + VipsThreadGate *memory; } VipsThreadProfile; gboolean vips__thread_profile = FALSE; @@ -92,10 +93,8 @@ vips_thread_gate_block_save( VipsThreadGateBlock *block, FILE *fp ) } static void -vips_thread_profile_save_gate( VipsObject *key, VipsObject *value, FILE *fp ) +vips_thread_profile_save_gate( VipsThreadGate *gate, FILE *fp ) { - VipsThreadGate *gate = (VipsThreadGate *) value; - fprintf( fp, "gate: %s\n", gate->name ); fprintf( fp, "start:\n" ); vips_thread_gate_block_save( gate->start, fp ); @@ -103,6 +102,15 @@ vips_thread_profile_save_gate( VipsObject *key, VipsObject *value, FILE *fp ) vips_thread_gate_block_save( gate->stop, fp ); } +static void +vips_thread_profile_save_cb( gpointer key, gpointer value, gpointer data ) +{ + VipsThreadGate *gate = (VipsThreadGate *) value; + FILE *fp = (FILE *) data; + + vips_thread_profile_save_gate( gate, fp ); +} + static void vips_thread_profile_save( VipsThreadProfile *profile ) { @@ -121,7 +129,8 @@ vips_thread_profile_save( VipsThreadProfile *profile ) fprintf( vips__thread_fp, "thread: %s (%p)\n", profile->name, profile ); g_hash_table_foreach( profile->gates, - (GHFunc) vips_thread_profile_save_gate, vips__thread_fp ); + vips_thread_profile_save_cb, vips__thread_fp ); + vips_thread_profile_save_gate( profile->memory, vips__thread_fp ); g_mutex_unlock( vips__global_lock ); } @@ -175,6 +184,19 @@ vips__thread_profile_init( void ) #endif } +static VipsThreadGate * +vips_thread_gate_new( const char *gate_name ) +{ + VipsThreadGate *gate; + + gate = g_new( VipsThreadGate, 1 ); + gate->name = gate_name; + gate->start = g_new0( VipsThreadGateBlock, 1 ); + gate->stop = g_new0( VipsThreadGateBlock, 1 ); + + return( gate ); +} + void vips__thread_profile_attach( const char *thread_name ) { @@ -193,6 +215,7 @@ vips__thread_profile_attach( const char *thread_name ) profile->gates = g_hash_table_new_full( g_direct_hash, g_str_equal, NULL, (GDestroyNotify) vips_thread_gate_free ); + profile->memory = vips_thread_gate_new( "memory" ); g_private_set( vips_thread_profile_key, profile ); } @@ -219,19 +242,6 @@ vips__thread_profile_detach( void ) } } -static VipsThreadGate * -vips_thread_gate_new( const char *gate_name ) -{ - VipsThreadGate *gate; - - gate = g_new( VipsThreadGate, 1 ); - gate->name = gate_name; - gate->start = g_new0( VipsThreadGateBlock, 1 ); - gate->stop = g_new0( VipsThreadGateBlock, 1 ); - - return( gate ); -} - static void vips_thread_gate_block_add( VipsThreadGateBlock **block ) { @@ -311,3 +321,26 @@ vips__thread_gate_stop( const char *gate_name ) VIPS_DEBUG_MSG( "\t %" G_GINT64_FORMAT "\n", time ); } } + +/* Record a malloc() or free(). Use -ve numbers for free. + */ +void +vips__thread_malloc_free( gint64 size ) +{ + VipsThreadProfile *profile; + + VIPS_DEBUG_MSG( "vips__thread_malloc_free: %zd\n", size ); + + if( (profile = vips_thread_profile_get()) ) { + gint64 time = vips_get_time(); + VipsThreadGate *gate = profile->memory; + + if( gate->start->i >= VIPS_GATE_SIZE ) { + vips_thread_gate_block_add( &gate->start ); + vips_thread_gate_block_add( &gate->stop ); + } + + gate->start->time[gate->start->i++] = time; + gate->stop->time[gate->stop->i++] = size; + } +} diff --git a/libvips/iofuncs/memory.c b/libvips/iofuncs/memory.c index fe95d338..455496aa 100644 --- a/libvips/iofuncs/memory.c +++ b/libvips/iofuncs/memory.c @@ -244,6 +244,8 @@ vips_tracked_free( void *s ) g_mutex_unlock( vips_tracked_mutex ); g_free( s ); + + VIPS_GATE_FREE( size ); } static void @@ -311,6 +313,8 @@ vips_tracked_malloc( size_t size ) g_mutex_unlock( vips_tracked_mutex ); + VIPS_GATE_MALLOC( size ); + return( buf ); }