support main thread gates

This commit is contained in:
John Cupitt 2013-11-26 13:01:40 +00:00
parent b746ab36d6
commit 3a195d4d5c
3 changed files with 56 additions and 21 deletions

View File

@ -41,6 +41,7 @@
#include <vips/vips.h> #include <vips/vips.h>
#include <vips/internal.h> #include <vips/internal.h>
#include <vips/debug.h>
#define VIPS_GATE_SIZE (1000) #define VIPS_GATE_SIZE (1000)
@ -103,13 +104,24 @@ vips_thread_profile_save_gate( VipsObject *key, VipsObject *value, FILE *fp )
} }
static void static void
vips_thread_profile_save( VipsThreadProfile *profile, FILE *fp ) vips_thread_profile_save( VipsThreadProfile *profile )
{ {
g_mutex_lock( vips__global_lock ); g_mutex_lock( vips__global_lock );
fprintf( fp, "thread: %s (%p)\n", profile->name, profile ); VIPS_DEBUG_MSG( "vips_thread_profile_save: %s\n", profile->name );
if( !vips__thread_fp ) {
vips__thread_fp =
vips__file_open_write( "vips-profile.txt", TRUE );
if( !vips__thread_fp )
vips_error_exit( "unable to create profile log" );
printf( "recording profile in vips-profile.txt\n" );
}
fprintf( vips__thread_fp, "thread: %s (%p)\n", profile->name, profile );
g_hash_table_foreach( profile->gates, g_hash_table_foreach( profile->gates,
(GHFunc) vips_thread_profile_save_gate, fp ); (GHFunc) vips_thread_profile_save_gate, vips__thread_fp );
g_mutex_unlock( vips__global_lock ); g_mutex_unlock( vips__global_lock );
} }
@ -117,8 +129,10 @@ vips_thread_profile_save( VipsThreadProfile *profile, FILE *fp )
static void static void
vips_thread_profile_free( VipsThreadProfile *profile ) vips_thread_profile_free( VipsThreadProfile *profile )
{ {
if( vips__thread_fp ) VIPS_DEBUG_MSG( "vips_thread_profile_free: %s\n", profile->name );
vips_thread_profile_save( profile, vips__thread_fp );
if( vips__thread_profile )
vips_thread_profile_save( profile );
VIPS_FREEF( g_hash_table_destroy, profile->gates ); VIPS_FREEF( g_hash_table_destroy, profile->gates );
VIPS_FREE( profile ); VIPS_FREE( profile );
@ -159,14 +173,6 @@ vips__thread_profile_init( void )
vips_thread_profile_key = g_private_new( vips_thread_profile_key = g_private_new(
(GDestroyNotify) vips_thread_profile_free ); (GDestroyNotify) vips_thread_profile_free );
#endif #endif
if( vips__thread_profile ) {
if( !(vips__thread_fp =
vips__file_open_write( "vips-profile.txt", TRUE )) )
vips_error_exit( "unable to create profile log" );
printf( "recording profile in vips-profile.txt\n" );
}
} }
void void
@ -178,6 +184,8 @@ vips__thread_profile_attach( const char *thread_name )
g_once( &once, (GThreadFunc) vips__thread_profile_init, NULL ); g_once( &once, (GThreadFunc) vips__thread_profile_init, NULL );
VIPS_DEBUG_MSG( "vips__thread_profile_attach: %s\n", thread_name );
g_assert( !g_private_get( vips_thread_profile_key ) ); g_assert( !g_private_get( vips_thread_profile_key ) );
profile = g_new( VipsThreadProfile, 1 ); profile = g_new( VipsThreadProfile, 1 );
@ -205,8 +213,10 @@ vips__thread_profile_detach( void )
{ {
VipsThreadProfile *profile; VipsThreadProfile *profile;
if( (profile = vips_thread_profile_get()) ) if( (profile = vips_thread_profile_get()) ) {
vips_thread_profile_free( profile ); vips_thread_profile_free( profile );
g_private_set( vips_thread_profile_key, NULL );
}
} }
static VipsThreadGate * static VipsThreadGate *
@ -251,7 +261,11 @@ vips__thread_gate_start( const char *gate_name )
{ {
VipsThreadProfile *profile; VipsThreadProfile *profile;
VIPS_DEBUG_MSG( "vips__thread_gate_start: %s\n", gate_name );
if( (profile = vips_thread_profile_get()) ) { if( (profile = vips_thread_profile_get()) ) {
gint64 time = vips_get_time();
VipsThreadGate *gate; VipsThreadGate *gate;
if( !(gate = if( !(gate =
@ -264,7 +278,9 @@ vips__thread_gate_start( const char *gate_name )
if( gate->start->i >= VIPS_GATE_SIZE ) if( gate->start->i >= VIPS_GATE_SIZE )
vips_thread_gate_block_add( &gate->start ); vips_thread_gate_block_add( &gate->start );
gate->start->time[gate->start->i++] = vips_get_time(); gate->start->time[gate->start->i++] = time;
VIPS_DEBUG_MSG( "\t %" G_GINT64_FORMAT "\n", time );
} }
} }
@ -273,7 +289,11 @@ vips__thread_gate_stop( const char *gate_name )
{ {
VipsThreadProfile *profile; VipsThreadProfile *profile;
VIPS_DEBUG_MSG( "vips__thread_gate_stop: %s\n", gate_name );
if( (profile = vips_thread_profile_get()) ) { if( (profile = vips_thread_profile_get()) ) {
gint64 time = vips_get_time();
VipsThreadGate *gate; VipsThreadGate *gate;
if( !(gate = if( !(gate =
@ -286,6 +306,8 @@ vips__thread_gate_stop( const char *gate_name )
if( gate->stop->i >= VIPS_GATE_SIZE ) if( gate->stop->i >= VIPS_GATE_SIZE )
vips_thread_gate_block_add( &gate->stop ); vips_thread_gate_block_add( &gate->stop );
gate->stop->time[gate->stop->i++] = vips_get_time(); gate->stop->time[gate->stop->i++] = time;
VIPS_DEBUG_MSG( "\t %" G_GINT64_FORMAT "\n", time );
} }
} }

View File

@ -220,7 +220,12 @@ vips__init( const char *argv0 )
g_free( prgname ); g_free( prgname );
vips__thread_profile_attach( "main" ); vips__thread_profile_attach( "main" );
VIPS_GATE_START( "main" );
/* We can't do VIPS_GATE_START() until command-line processing
* happens, since vips__thread_profile may not be set yet. Call
* directly.
*/
vips__thread_gate_start( "main" );
/* Try to discover our prefix. /* Try to discover our prefix.
*/ */
@ -377,8 +382,17 @@ vips_shutdown( void )
im_close_plugins(); im_close_plugins();
VIPS_GATE_STOP( "main" ); /* Mustn't run this more than once.
*/
{
static gboolean done = FALSE;
if( !done )
VIPS_GATE_STOP( "main" );
}
vips__thread_profile_detach(); vips__thread_profile_detach();
vips__thread_profile_stop();
/* In dev releases, always show leaks. But not more than once, it's /* In dev releases, always show leaks. But not more than once, it's
* annoying. * annoying.

View File

@ -61,7 +61,6 @@ class Event:
thread.events.append(self) thread.events.append(self)
input_filename = 'vips-profile.txt' input_filename = 'vips-profile.txt'
thread_id = 0 thread_id = 0
@ -217,7 +216,7 @@ def draw_event(ctx, event):
ctx.move_to(left + width / 2 - twidth / 2, top + theight) ctx.move_to(left + width / 2 - twidth / 2, top + theight)
ctx.set_source_rgb(1.00, 0.83, 0.00) ctx.set_source_rgb(1.00, 0.83, 0.00)
ctx.show_text(event.gate_name) ctx.show_text(event.gate_name)
ctx.stroke() #ctx.stroke()
for thread in threads: for thread in threads:
xbearing, ybearing, twidth, theight, xadvance, yadvance = \ xbearing, ybearing, twidth, theight, xadvance, yadvance = \
@ -225,7 +224,7 @@ for thread in threads:
ctx.move_to(0, theight + thread.total_y * PIXELS_PER_GATE) ctx.move_to(0, theight + thread.total_y * PIXELS_PER_GATE)
ctx.set_source_rgb(1.00, 1.00, 1.00) ctx.set_source_rgb(1.00, 1.00, 1.00)
ctx.show_text(thread.thread_name) ctx.show_text(thread.thread_name)
ctx.stroke() #ctx.stroke()
for event in thread.events: for event in thread.events:
draw_event(ctx, event) draw_event(ctx, event)