much faster vips_argument_map()

improve the way we handle looping over args, gets us back to 7.26 speed
for example workspaces
This commit is contained in:
John Cupitt 2012-06-01 14:20:20 +01:00
parent faa2f820c6
commit 2cf57c123d
3 changed files with 66 additions and 35 deletions

View File

@ -1,6 +1,7 @@
19/4/12 started 7.28.6
- better resolution unit handling in deprecated im_vips2tiff()
- use TIFF_CFLAGS output from pkg-config (thanks Jay)
- much faster vips_argument_map()
19/4/12 started 7.28.5
- ifthenelse blend mode was broken

View File

@ -328,15 +328,8 @@ int vips_object_get_argument_priority( VipsObject *object, const char *name );
VipsArgumentInstance *ARG_INSTANCE = \
vips__argument_get_instance( argument_class, \
VIPS_OBJECT( OBJECT ) ); \
\
/* We have many props on the arg table ... filter out the \
* ones for this class. \
*/ \
if( g_object_class_find_property( \
G_OBJECT_CLASS( object_class ), \
g_param_spec_get_name( PSPEC ) ) == PSPEC ) {
#define VIPS_ARGUMENT_FOR_ALL_END } } }
#define VIPS_ARGUMENT_FOR_ALL_END } }
/* And some macros to collect args from a va list.
*/
@ -494,13 +487,22 @@ struct _VipsObjectClass {
*/
const char *description;
/* Table of arguments for this class and any derived classes. Order
* is important, so keep a traverse list too. We can't rely on the
* ordering given by g_object_class_list_properties() since it comes
* from a hash :-(
/* Hash from pspec to VipsArgumentClass.
*
* This records the VipsArgumentClass for every pspec used in
* VipsObject and any subclass (ie. everywhere), so it's huge. Don't
* loop over this hash! Fine for lookups though.
*/
VipsArgumentTable *argument_table;
/* A sorted (by priority) list of the VipsArgumentClass for this class
* and any superclasses. This is small and specific to this class.
*
* Use the stored GType to work out when to restart the list for a
* subclass.
*/
GSList *argument_table_traverse;
GType argument_table_traverse_gtype;
};
gboolean vips_value_is_null( GParamSpec *psoec, const GValue *value );

View File

@ -355,9 +355,11 @@ vips_argument_map( VipsObject *object,
g_object_ref( object );
VIPS_ARGUMENT_FOR_ALL( object,
pspec, argument_class, argument_instance ) {
pspec, argument_class, argument_instance ) {
void *result;
/* argument_instance should not be NULL.
*/
g_assert( argument_instance );
if( (result = fn( object, pspec,
@ -388,19 +390,12 @@ vips_argument_class_map( VipsObjectClass *object_class,
(VipsArgumentClass *) p->data;
VipsArgument *argument = (VipsArgument *) arg_class;
GParamSpec *pspec = argument->pspec;
/* We have many props on the arg table ... filter out the
* ones for this class.
*/
if( g_object_class_find_property(
G_OBJECT_CLASS( object_class ),
g_param_spec_get_name( pspec ) ) == pspec ) {
void *result;
if( (result =
fn( object_class, pspec, arg_class, a, b )) )
return( result );
}
void *result;
if( (result =
fn( object_class, pspec, arg_class, a, b )) )
return( result );
}
return( NULL );
@ -749,15 +744,11 @@ vips_object_dispose( GObject *gobject )
/* Our subclasses should have already called this. Run it again, just
* in case.
*/
if( !object->preclose ) {
#ifdef VIPS_DEBUG
printf( "vips_object_dispose: no vips_object_preclose() " );
vips_object_print_name( VIPS_OBJECT( gobject ) );
printf( "\n" );
#endif /*VIPS_DEBUG*/
vips_object_preclose( object );
}
#ifdef DEBUG
if( !object->preclose )
printf( "vips_object_dispose: pre-close missing!\n" );
#endif /*DEBUG*/
vips_object_preclose( object );
/* Clear all our arguments: they may be holding resources we should
* drop.
@ -1377,7 +1368,8 @@ vips_object_class_install_argument( VipsObjectClass *object_class,
VipsArgumentClass *argument_class = g_new( VipsArgumentClass, 1 );
#ifdef DEBUG
printf( "vips_object_class_install_argument: %s %s\n",
printf( "vips_object_class_install_argument: %p %s %s\n",
object_class,
g_type_name( G_TYPE_FROM_CLASS( object_class ) ),
g_param_spec_get_name( pspec ) );
#endif /*DEBUG*/
@ -1401,10 +1393,46 @@ vips_object_class_install_argument( VipsObjectClass *object_class,
vips_argument_table_replace( object_class->argument_table,
(VipsArgument *) argument_class );
/* If this is the first argument for a new subclass, we need to clone
* the traverse list we inherit.
*/
if( object_class->argument_table_traverse_gtype !=
G_TYPE_FROM_CLASS( object_class ) ) {
#ifdef DEBUG
printf( "vips_object_class_install_argument: "
"cloning traverse\n" );
#endif /*DEBUG*/
object_class->argument_table_traverse =
g_slist_copy( object_class->argument_table_traverse );
object_class->argument_table_traverse_gtype =
G_TYPE_FROM_CLASS( object_class );
}
object_class->argument_table_traverse = g_slist_prepend(
object_class->argument_table_traverse, argument_class );
object_class->argument_table_traverse = g_slist_sort(
object_class->argument_table_traverse, traverse_sort );
#ifdef DEBUG
{
GSList *p;
printf( "%d items on traverse %p\n",
g_slist_length( object_class->argument_table_traverse ),
&object_class->argument_table_traverse );
for( p = object_class->argument_table_traverse; p; p = p->next ) {
VipsArgumentClass *argument_class =
(VipsArgumentClass *) p->data;
printf( "\t%p %s\n",
argument_class,
g_param_spec_get_name(
((VipsArgument *) argument_class)->pspec ) );
}
}
#endif /*DEBUG*/
}
/* Set a named arg from a string.