I was following example shown in this youtube video () which illustrates superiority of filtering methods in Revit API over usual iteration. But my code is significantly slower than the the iteration method :
filter method-0.16 secs
iteration method-0.06 secs
My code using filter method is :
import Autodesk.Revit.DB as DB doc=__revit__.ActiveUIDocument.Document uidoc=__revit__.ActiveUIDocument height_param_id=DB.ElementId(DB.BuiltInParameter.WALL_USER_HEIGHT_PARAM) height_param_prov=DB.ParameterValueProvider(height_param_id) param_equality=DB.FilterNumericEquals() # equality class height_value_rule=DB.FilterDoubleRule(height_param_prov,param_equality,10,1e-02) param_filter=DB.ElementParameterFilter(height_value_rule) # This program significantly slows down for the next line walls=DB.FilteredElementCollector(doc)\ .WherePasses(param_filter)\ .ToElementIds() uidoc.Selection.SetElementIds(walls) For iteration following code was used.
from System.Collections.Generic import List import Autodesk.Revit.DB as DB doc=__revit__.ActiveUIDocument.Document uidoc=__revit__.ActiveUIDocument sheet_collector=DB.FilteredElementCollector(doc)\ .OfCategory(DB.BuiltInCategory\ .OST_Sheets)\ .WhereElementIsNotElementType()\ .ToElements() walls=DB.FilteredElementCollector(doc)\ .OfCategory(DB.BuiltInCategory.OST_Walls)\ .WhereElementIsNotElementType()\ .ToElements() tallwallsids=[] for wall in walls: heightp=wall.LookupParameter('Unconnected Height') if heightp and heightp.AsDouble()==10: tallwallsids.append(wall.Id) uidoc.Selection.SetElementIds(List[DB.ElementId](tallwallsids)) 2 Answers
This makes sense if you consider the amount of elements that the two methods have to consider. First method:
walls=DB.FilteredElementCollector(doc)\ .WherePasses(param_filter)\ .ToElementIds() In this method you are asking the filter to consider ALL elements in the model. That's potentially a lot of elements to pass through the filter. That's opposed to:
walls=DB.FilteredElementCollector(doc)\ .OfCategory(DB.BuiltInCategory.OST_Walls)\ .WhereElementIsNotElementType()\ .ToElements() In this method you use the QUICK filter OfCategory() and another WhereElementIsNotElementType() to narrow down the selection to only Wall instances. Even though you follow that through with a simple for loop which is the slow component here, its still FASTER than passing ALL elements in the model through the first filter.
You can optimize it by creating a filter like so:
walls=DB.FilteredElementCollector(doc)\ .OfCategory(DB.BuiltInCategory.OST_Walls)\ .WhereElementIsNotElementType()\ .WherePasses(param_filter) .ToElements() This would actually combine the quick category filter, element type filter, and slow parameter filter to potentially be an overall faster and easier to read solution.
Give it a go, and let me know if this makes sense.
Cheers!
1What iteration method?
Nowadays, filtered element collectors are normally the only way to retrieve and iterate over Revit database elements.
The filtered element collector in itself is probably fast.
If you have a huge number of walls and your memory is limited, the call to ToElementIds may consume significant resources.
SetElementIds may also cost time.
Check out the extensive Revit API forum discussion on filtered element collector by pipe system types for more on this.
I suggest you provide a complete minimal reproducible sample case equipped with benchmarking code for each of those method calls to prove the performance degradation.
1