Regeneration Option Best Practices

Our discussion of the risks of using the manual regeneration option triggered several very interesting comments and suggestions. Here are some important fundamental things to note about the regeneration modes:

Best Practices Round 1

Here is a first take at some best practices for dealing with the regeneration option, suggested by Harry Mattison and Arnošt Lobel of the Revit development team and based on the suggestion by David:

Suggestion: If automatic regeneration will be going away in a future release, one would think the only thing a responsible developer whose code will need to work beyond Revit 2011 can do is to deal with this issue NOW, while the code is as small and simple as it is likely to ever be, compared to the future.

That being the case, developers will *need* to know (soon) what the official Best Practices are for maximizing the life of existing code in a manual regeneration world.

Is it to call for regeneration after every change, or every group of query-free changes?

That seems difficult to remember as you're writing code...

One would assume there is a performance cost for calling for a manual regeneration. Is it usually significant?

Would an application that makes many query-free changes in a row, then call for one regeneration at the end, get better performance than one that is running in Automatic mode? One would think so, if in Automatic mode a regeneration is happening after each change. But without knowing the general performance impact level of a regeneration, one has to ask: Would it even be noticeable?

Being aware of the situation is great (thank you very much!), but it would be nice if developers of long-term code could get some more extensive/explicit guidance.

Response: 1. The "best practice" is to use manual regeneration and invoke regeneration only when needed. For example, regenerate must be called before reading data from a changed model. The performance of regeneration will depend on the magnitude of change and the complexity of the model – there is no simple and generic answer about how long regeneration will take.

2. It's difficult ;-) I do not think there is one best approach. An ideal approach could differ from application to application. There are a few solid points though, that programmers could use as a reference:

Many thanks to David for raising this issue and to Harry and Arnošt for their responses!

Best Practices Round 2

During the course of the day, several new comments were posted, and I was able to discuss these further with my colleagues in the development team, especially Arnošt (again) and Scott Conover. First, here are the additional comments:

David said: It would be nice if there were some type of "RegenerationNeeded" Boolean method available. But it seems like there may be better ways for Revit to do this. For example, it would be GREAT if "Automatic" mode stayed, but changed how it worked: not be calling Regenerate internally after every change, but rather to have Revit simply call Regenerate INSTEAD of throwing an exception that is caused by the need for a Regenerate. Thus Regenerate would only get called when needed, and automatically by Revit, thus maximizing performance, without any special knowledge needed by the developer. To me, if that were possible it seems like the best of both worlds.

Fernando Malard said: In my personal opinion, most of the cases the Automatic mode will solve the problem. Revit should be smart enough to just refresh those changed elements. This is related on how the Reactor mechanism is connected to the regeneration mechanism and how it monitors the changed elements. I really think it is strange to introduce a concept (this new "Automatic" Attribute) already marked as "to be removed soon". This will freak people and no one will use it (I have used because I don't want to review my code because it won't cause any significant impact). I believe most of Revit developers won't do this either. I agree with the idea of "Automatic" being kept and just tweaked to work as smart as possible. It will satisfy most of the cases and just when the user wants to really avoid the auto Regeneration he should change the attribute to "Manual" and handle his code flow. Another approach would be to create something like a PUSH/PULL Auto refresh feature which would empower the user to have control when to turn off auto refresh and when turn it back on after doing his heavy procedures. Does not make much sense to obligate people to control a mechanism when most of time its automatic mode will be suitable for them.

Response:

As stated above, the automatic option is not new. That is the mode that Revit has been using all along so far. Developers complained that it is too slow, so we introduced the several different mechanisms to improve performance, such as the SuspendUpdating mechanism and the 'Batch Creation' methods in Autodesk.Revit.Creation.Document. We continued to get requests to enhance SuspendUpdating to cover more types of changes, and that led to the new manual regeneration option, providing even more optimisation possibilities, tighter integration into Revit and better access to the internal functionality.

Automatic regeneration is as 'intelligent' as it can be right now. It knows enough not to do anything when there are no changes. It knows enough to only update elements which have been changed, and elements to which changes propagate because of relationships. But sometimes the performance hit from each successive change (for example, setting of 15 parameters on 100 instances) can add up.

Manual regeneration is exactly the same routine used in Automatic regeneration (it knows not to do anything when nothing is needed, etc). The add-in application has total control over when it is invoked. This allows your application logic to minimize the number of calls, by only calling it when you really need to read data from a potentially modified element.

The automatic option is not new, there just was no other choice previously. When we discussed how to add the attributes to choose between manual and automatic, we considered making a default. It turned out that there is no reasonable default: automatic is what existing code was written to expect, but not what developers were asking for or what we deem useful for moving forward. So there is no default value for this attribute, and you must apply the Automatic value explicitly and endure the compiler warning.

I hope that this helps clarify the issue and look forward to hearing what performance improvements can be achieved with the new option.