In small TBX files there is rarely a need to consider code optimisation, but as your files grow in note count and complexity and acquire more agents you may see the time-to update increase, i.e. how quickly code changes are effected. In such circumstances, or just as best practice, it is worth reviewing and applying a few optimisation techniques.
These do not directly affect code execution (other than by bad syntax) but help make everything else easier.
Using prototypes to set up and/or locate discrete sets of note(s) is a big productivity gain. Editing code (or code notes) once can then affect many notes. Consider using $RuleDisabled and $DisplayExpressionDisabled in the prototype so as to suppress execution of such code in the prototype. If applying prototypes as part of incremental formalisation, do not forget to reset the inheritance of any prototype-using note's attributes that may have previously had a local value set.
Check your syntax
Make sure your code does not include deprecated syntax. At some point in the future the code may not work at all and in the meantime you're making Tinderbox guess your real intent. Tinderbox does not warn about the existence deprecated code (it can't know what things are that the parser doesn't 'understand'), so updating code is an exercise left to the user.
Act on the right subject: originals vs. aliases
Be aware that if using actions in agents, you are acting on the original, so values of intrinsic attributes
These techniques can help with tuning performance once the size and complexity of your TBX grows:
- Narrow the scope of agent search. Review and rewrite queries so each successive query terms tests fewer items. The fewer tests, in aggregate that Tinderbox has to make the faster the results. This is especially true if the (final) tests is based on a complex regular expression such as in .contains(). If the desired matching group of notes is not easily defined in narrow scope, consider giving them all the same prototype.
- Querying existing agents. Rather than have numerous agent all querying the same overall scope, consider making one agent to to that first selection and then have other agents query that agent's results using different queries. So rather than have 5 agents querying descendedFrom("X"), make a single agent, e.g. 'agent A', do the latter and the the other use inside("agent A") as their first query term. Do note though that this means it may take several agent cycles for a change to cycle through.
- Agent Priority ($AgentPriority). Not every agent needs to run every cycle. The agent's priority can be set via the agent's Action Inspector's Query sub-tab or directly in code via $AgentPriority. Also consider an agent to find all agents allowing you to easily adjust their $AgentPriority via its action. Or make a stamp to toggle $AgentPriority on/off.
- Re-use agents as part of queries. Queries can match aliases in other agents. If using multiple agents all with the same query start and differing final filter, it is more efficient to use one agent to find the initial query scope and then make the other agents query that one agent for the extra term. Consider an 10 agents testing the whole TBX of 1,000 notes, to match the same 100 notes then testing those to get the actual full matches. That is 1,000+100 x 10, i.e. 11,000 test in total. Now if one agent does the first match (1,000 tests) and 10 agents test its 100 aliases, we get 1,000 + (100 x 10) to give 2,000 test—just 18% of the original number of tests per agent cycle. This isn't apparent in small files, but the effects pile up as a document grows especially if the user is keen on using agents for everything. If employing this chaining, be aware of the possibility of cascade effects for which to allow.
- Caching expression results in a user attribute. Expressions like Display Expressions and Hover Expressions are, slower to run than rules or agent actions; this is especially so if the expression is anything but a simple attribute value call. As a result, if such expressions are complex, it is better to use a rule or agent action to run the code and store the expression's result in a user attribute and then have the display/hover expression simply read that stored value. Adding an extra attribute has negligible impact on the TBX.
- Use $Searchable to exclude notes. The $Searchable attribute provides an ad hoc way to exclude some notes from all searches.
- Make the action remove acted on notes from query scope. Consider making the action's outcome make changes such that the altered note no longer meets the initial query. This is a good method for making an agent effectively act once only on a note. If it is not possible to alter an attribute value being matched, e.g. it is $Text that must not be changed, consider either moving the note (via $Container), or making a user Boolean as a 'guard' field to be tested in the query for the action to set (e.g. an $IsCorrected).