Performance Adviser

Performance Adviser

The performance adviser feature of the Revit API is designed to analyze a document and flag for the user any elements and/or settings that may cause performance degradation. The Performance Adviser command executes a set of rules and displays their result in a standard review warnings dialog.

The API for performance adviser consists of 2 classes:

Performance Adviser

PerformanceAdviser is used to add or delete rules to be checked, enable and disable rules, get information about rules in the list, and to execute some or all rules in the list. Applications that create new rules are expected to use AddRule() to register the new rule during application startup and DeleteRule() to deregister it during application shutdown. ExecuteAllRules() will execute all rules in the list on a given document, while ExecuteRules() can be used to execute selected rules in a document. Both methods will return a list of failure messages explaining performance problems detected in the document.

The following example demonstrates looping through all performance adviser rules and executing all the rules for a document.

Code Region: Performance Adviser

//Get the name of each registered PerformanceRule and then execute all of them.
foreach (PerformanceAdviserRuleId id in PerformanceAdviser.GetPerformanceAdviser().GetAllRuleIds())
{
    string ruleName = PerformanceAdviser.GetPerformanceAdviser().GetRuleName(id);
}
PerformanceAdviser.GetPerformanceAdviser().ExecuteAllRules(document);

IPerformanceAdviserRule

Create an instance of the IPerformanceAdviserRule interface to create new rules for the Performance Adviser. Rules can be specific to elements or can be document-wide rules. The following methods need to be implemented:

  • GetName() - a short string naming the rule
  • GetDescription() - a one to two sentence description of the rule
  • InitCheck() -method invoked by performance advisor once in the beginning of the check. If rule checks the document as a whole rather than specific elements, the check should be performed in this method.
  • FinalizeCheck() - method invoked by performance advisor once in the end of the check. Any problematic results found during rule execution can be reported during this message using FailureMessage(s)
  • WillCheckElements() - indicates if rule needs to be executed on idividual elements
  • GetElementFilter() - retrieves a filter to restrict elements to be checked
  • ExecuteElementCheck() - method invoked by performance advisor for each element to be checked

The following excerpt from the PerformanceAdviserControl sample in the Revit API SDK Samples folder demonstrates the implementation of a custom rule used to identify any doors in the document that are face-flipped. (See the sample project for the complete class implementation.)

Code Region: Implementing IPerformanceAdviserRule

public class FlippedDoorCheck : Autodesk.Revit.DB.IPerformanceAdviserRule
{
    #region Constructor
    /// <summary>
    /// Set up rule name, description, and error handling
    /// </summary>
    public FlippedDoorCheck()
    {
        m_name = "Flipped Door Check";
        m_description = "An API-based rule to search for and return any doors that are face-flipped";
        m_doorWarningId = new Autodesk.Revit.DB.FailureDefinitionId(new Guid("25570B8FD4AD42baBD78469ED60FB9A3"));
        m_doorWarning = Autodesk.Revit.DB.FailureDefinition.CreateFailureDefinition(m_doorWarningId, Autodesk.Revit.DB.FailureSeverity.Warning, "Some doors in this project are face-flipped.");
    }
    #endregion

    #region IPerformanceAdviserRule implementation
    /// <summary>
    /// Does some preliminary work before executing tests on elements.  In this case,
    /// we instantiate a list of FamilyInstances representing all doors that are flipped.
    /// </summary>
    /// <param name="document">The document being checked</param>
    public void InitCheck(Autodesk.Revit.DB.Document document)
    {
       if (m_FlippedDoors == null)
          m_FlippedDoors = new List<Autodesk.Revit.DB.ElementId>();
       else
          m_FlippedDoors.Clear();
       return;
    }
    
    /// <summary>
    /// This method does most of the work of the IPerformanceAdviserRule implementation.
    /// It is called by PerformanceAdviser.
    /// It examines the element passed to it (which was previously filtered by the filter
    /// returned by GetElementFilter() (see below)).  After checking to make sure that the
    /// element is an instance, it checks the FacingFlipped property of the element.
    ///
    /// If it is flipped, it adds the instance to a list to be used later.
    /// </summary>
    /// <param name="document">The active document</param>
    /// <param name="element">The current element being checked</param>
    public void ExecuteElementCheck(Autodesk.Revit.DB.Document document, Autodesk.Revit.DB.Element element)
    {
        if ((element is Autodesk.Revit.DB.FamilyInstance))
        {
             Autodesk.Revit.DB.FamilyInstance doorCurrent = element as Autodesk.Revit.DB.FamilyInstance;
             if (doorCurrent.FacingFlipped)
                 m_FlippedDoors.Add(doorCurrent.Id);
        }
         
    }

    /// <summary>
    /// This method is called by PerformanceAdviser after all elements in document
    /// matching the ElementFilter from GetElementFilter() are checked by ExecuteElementCheck().
    ///
    /// This method checks to see if there are any elements (door instances, in this case) in the
    /// m_FlippedDoor instance member.  If there are, it iterates through that list and displays
    /// the instance name and door tag of each item.
    /// </summary>
    /// <param name="document">The active document</param>
    public void FinalizeCheck(Autodesk.Revit.DB.Document document)
    {
        if (m_FlippedDoors.Count == 0)
            System.Diagnostics.Debug.WriteLine("No doors were flipped.  Test passed.");
        else
        {
            //Pass the element IDs of the flipped doors to the revit failure reporting APIs.
            Autodesk.Revit.DB.FailureMessage fm = new Autodesk.Revit.DB.FailureMessage(m_doorWarningId);
            fm.SetFailingElements(m_FlippedDoors);
            Autodesk.Revit.DB.Transaction failureReportingTransaction = new Autodesk.Revit.DB.Transaction(document, "Failure reporting transaction");
            failureReportingTransaction.Start();
            document.PostFailure(fm);
            failureReportingTransaction.Commit();
            m_FlippedDoors.Clear();
        }
    }
    
    /// <summary>
    /// Gets the description of the rule
    /// </summary>
    /// <returns>The rule description</returns>
    public string GetDescription()
    {
        return m_description;
    }

    /// <summary>
    /// This method supplies an element filter to reduce the number of elements that PerformanceAdviser
    /// will pass to GetElementCheck().  In this case, we are filtering for door elements.
    /// </summary>
    /// <param name="document">The document being checked</param>
    /// <returns>A door element filter</returns>
    public Autodesk.Revit.DB.ElementFilter GetElementFilter(Autodesk.Revit.DB.Document document)
    {
        return new Autodesk.Revit.DB.ElementCategoryFilter(Autodesk.Revit.DB.BuiltInCategory.OST_Doors);
    }

    /// <summary>
    /// Gets the name of the rule
    /// </summary>
    /// <returns>The rule name</returns>
    public string GetName()
    {
        return m_name;
    }

    /// <summary>
    /// Returns true if this rule will iterate through elements and check them, false otherwise
    /// </summary>
    /// <returns>True</returns>
    public bool WillCheckElements()
    {
        return true;
    }

    #endregion
}