Search code examples
djangodjango-signalsdjango-debug-toolbar

Django: Do many signals slow down performance?


The debug_toolbar tells me I have 44 receivers from 12 signals both in the frontend and in the django-admin. Is that normal? Does this slow down performance? Is there anything I should check/fix according to you?

I might have messed up something with pinax, I notice that there are also many queries that seem to repeat. (checked and the queries seem to be ok)

This is the output of the toolbar:

class_prepared  class   setup_join_cache, ensure_default_manager, do_pending_lookups, prep_localized_datetime
connection_created  connection  
got_request_exception   request _rollback_on_exception
post_delete instance, using 
post_init   instance    TagAutocompleteTagItField._update, TagAutocompleteTagItField._update, ImageField.update_dimension_fields, ImageField.update_dimension_fields, ImageField.update_dimension_fields, TagAutocompleteTagItField._update, TagAutocompleteTagItField._update, TagAutocompleteTagItField._update, ImageField.update_dimension_fields, ImageField.update_dimension_fields, ImageField.update_dimension_fields, TagAutocompleteTagItField._update, TagAutocompleteTagItField._update, TagAutocompleteTagItField._update, ImageField.update_dimension_fields, ImageField.update_dimension_fields
post_save   instance, created, using, raw   create_account, superuser_email_address, create_profile, signup_code_result_save, TagAutocompleteTagItField._save, TagAutocompleteTagItField._save, TagAutocompleteTagItField._save, TagAutocompleteTagItField._save, TagAutocompleteTagItField._save, TagAutocompleteTagItField._save, TagAutocompleteTagItField._save, TagAutocompleteTagItField._save
post_syncdb app, verbosity, interactive, class, created_models  
pre_delete  instance, using 
pre_init    instance, args, kwargs  GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init, GenericForeignKey.instance_pre_init
pre_save    instance, using, raw    
request_finished        close_connection
request_started     reset_queries

TagAutocompleteTagItField is a subclass of django-tagging


Solution

  • Signals are synchronous, so they'll contribute to the processing time of any request in which they're called. So whether or not performance is being affected depends on what's being done in those functions.

    In your case there seems to be a lot going on on model instantiation / saving coming from your fields.

    That isn't the default django ImageField connecting all those signals right? It looks like there's a signal being connected per field in your project there.

    In any case, those TagAutocompleteTagItField and ImageFields seem to be adding most of your signals. The overhead for models that don't have those fields will be along the lines of checking each field in the model for a match, something like:

    tag_fields = [field for field in c._meta.fields if type(field) == TagAutocompleteTagItField]
    
    if tag_fields:
        # Do stuff
    

    That shouldn't be that bad really.

    If you have a tonne of those fields it might be worth testing it by disabling those TagAutocompleteTagItField and ImageField signals. Then if it's a drain, look in to whether you can move some of the logic in the signals somewhere else, for example calculating ImageField's dimensions when they're accessed.

    But.. I wouldn't. Not yet anyway. Remember that "premature optimization is the root of all evil"!