﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc	blockedby	blocking	notify_on_close	platform	project
2931	Built in method to profile trigger firings	Tristan Croll	Eric Pettersen	"I'm once again doing some profiling (trying to work out why adding an amino acid residue to a large model gets *really* slow when ISOLDE is active - ~6s to extend a chain by one residue in a megadalton complex). About 1 second of this is covered if I %prun the method itself (source code at https://github.com/tristanic/isolde/blob/af87760f3793fe9bb2e42ce0b73c8c91094ec9af/isolde/src/atomic/building/build_utils.py#L110), and the rest is presumably in methods firing in response to the `changes` trigger. To track down some similar performance issues in #2355 I hacked the below into `triggerset.py`... I'm wondering if it would be worth including something like this permanently - perhaps extended to allow accumulating a profile over the next ''n'' triggers, or even to profile **all** triggers for a set period of time? Seems it would be quite useful as the ChimeraX ecosystem becomes more complex.



{{{
class _Trigger:
    """"""Keep track of handlers to invoke when activated""""""

    def __init__(self, name, usage_cb, default_one_time, remove_bad_handlers):
        self._name = name
        from .orderedset import OrderedSet
        self._handlers = OrderedSet()	# Fire handlers in order they were registered.
        self._pending_add = set()
        self._pending_del = set()
        self._locked = 0
        self._blocked = 0
        self._need_activate = set()
        self._need_activate_data = []
        self._usage_cb = usage_cb
        self._default_one_time = default_one_time
        self._remove_bad_handlers = remove_bad_handlers
        self._profile_next_run = False
        self._profile_params = None

    def profile_next_run(self, sort_by='time', num_entries=20):
        self._profile_next_run = True
        self._profile_params = {'sort_by': sort_by, 'num_entries': num_entries}

    def activate(self, data):
        if not self._profile_next_run:
            self._activate(data)
            return
        import cProfile, pstats, io
        params = self._profile_params
        pr = cProfile.Profile()
        pr.enable()
        self._activate(data)
        pr.disable()
        s = io.StringIO()
        ps = pstats.Stats(pr, stream=s).sort_stats(params['sort_by'])
        ps.print_stats(params['num_entries'])
        print('Profile for last activation of {} trigger:'.format(self._name))
        print(s.getvalue())
        self._profile_next_run = False


    def _activate(self, data):
        # original, unchanged activate method
}}}"	enhancement	closed	moderate		Performance		fixed		chimera-programmers				all	ChimeraX
