SetElementIds two times slower than Revit's window selection

SetElementIds two times slower than Revit's window selection

DanielKP2Z9V
Advocate Advocate
1,178 Views
15 Replies
Message 1 of 16

SetElementIds two times slower than Revit's window selection

DanielKP2Z9V
Advocate
Advocate

I'm trying to select all elements in the view to avoid having to drag window (PickBox) each time. However, whatever I do commandData.Application.ActiveUIDocument.Selection.SetElementIds method is always about two times slower, which can make a difference on larger projects.

 

Has SetElementIds been made purposefully slower or have I done something wrong?

 

The simplest example:

 

 

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace scripts
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class SelectAllElementsInViewAndInGroups : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            Document doc = commandData.Application.ActiveUIDocument.Document;
            UIDocument uiDoc = commandData.Application.ActiveUIDocument;

            var elementIdsInView = new FilteredElementCollector(doc, doc.ActiveView.Id)
                .ToElementIds();

            // Set the selection to these filtered elements
            uiDoc.Selection.SetElementIds(elementIdsInView);

            return Result.Succeeded;
        }
    }
}

 

 

 

Version to exclude elements inside groups (based on the comments below):

 

 

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Collections.Generic;
using System.Linq;

namespace scripts
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class SelectAllElementsInView : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            Document doc = commandData.Application.ActiveUIDocument.Document;
            UIDocument uiDoc = commandData.Application.ActiveUIDocument;
            View currentView = doc.ActiveView;

            List<ElementId> ElementsNotInGroups = new FilteredElementCollector(doc, doc.ActiveView.Id)
                .WhereElementIsNotElementType()
                .Where(e => e.GroupId == ElementId.InvalidElementId)
                .Select(e => e.Id)
                .ToList();

            uiDoc.Selection.SetElementIds(ElementsNotInGroups);

            return Result.Succeeded;
        }
    }
}

 

 

 

0 Likes
1,179 Views
15 Replies
Replies (15)
Message 2 of 16

Moustafa_K
Collaborator
Collaborator

How did you bench mark this, to conclude almost double time. was it only at the statement `uiDoc.Selection.SetElementIds(elementIdsInView);` or the whole command action "filter and selection statements"?

 

I also noticed looping and filtering elements for each category is kind of expensive process. You can combine all the categories you wish to filter into LogicOrFilter  and pass them as a one call to the FilteredElementCollector.  

 

 

IList<ElementFilter> filterList = new List<ElementFilter>();

foreach (var cat in selectedCategories)
{
    filterList.Add(new ElementCategoryFilter(cat));
}

LogicalOrFilter combinedFilters = new LogicalOrFilter(filterList);

var elementIds = new FilteredElementCollector(Doc)
                        .WherePasses(combinedFilters)
                        .WhereElementIsNotElementType()
                        .ToElementIds();

 

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
Message 3 of 16

DanielKP2Z9V
Advocate
Advocate

Just manually with a stopwatch and selecting large enough sets of objects to get to 2 vs 4 or 4 vs 8 seconds differences (they seemed fairly consistently twice as long for API SetElementIds method).

 

Just to be clear everything up to calling SetElementIds is fast - actually that made me realize how fast FilteredElementCollector can be in general, but once you call SetElementIds for seemingly the same set of objects Revit takes about twice as long as if you just selected them with the manual mouse pickbox.

0 Likes
Message 4 of 16

TripleM-Dev.net
Advisor
Advisor

Hi @DanielKP2Z9V,

 

My guess; the selections made between the API Function and manual selction aren't identical, maybe even worksharing could be a issue.

 

Have you checked the resulting selected element count (in UI for both selections, and also the "elementIdsInView" count to compare to the actual elements set as selection).

 

The first function will select everything in the view, when selecting manually you may not select all.

Think about groups, curtainwalls, nested families etc, with a window selection only the top element will be selected and not the elements inside. Further in the SetElementIds method elements can be passed that may not be selectable.

 

All this could account for some delay, but even a manual selection of 2 sec. seems a bit off (sounds like a large selection to me)

 

The second method is titled "More elaborate version trying to exclude elements inside groups", but then doesn't exclude elements in groups.

Seems to me a attempt to exlude elements that have no category (this can occur), but to filter out those just select all and expand the linq command to exclude elements without a valid category.

Same can be done to exclude elements in groups, check if the Elements groupid = ElementId.invalid.

 

below a sample to exclude all elements in groups.

 

 List<ElementId> ElementsNotInGroups = new FilteredElementCollector(doc, doc.ActiveView.Id).WhereElementIsNotElementType().Where(e => e.GroupId == ElementId.InvalidElementId).Select(e => e.Id).ToList();

 

- Michel

 

Ps. I did a test with some selection functions of my own:

Setup; 20000 walls (no worksharing), there was no noticeable difference between manual and automated selection, if the manual could be actually "timed" it would be somewhat slower as during the window drag elements already get selected and slows down the selection, So I actually see the reverse.

And my automated selection do a lot behind the scene (multiselect by previous selected type(s))

 

Message 5 of 16

DanielKP2Z9V
Advocate
Advocate

@TripleM-Dev.net you are right, the example I've posted here is incorrect, I've replaced it with the code you posted, however it resulted in a similar slow down in my model - running this command is about twice as slow as selecting objects manually with pickbox.

0 Likes
Message 6 of 16

Moustafa_K
Collaborator
Collaborator

this is kinda weird. I didn't reach a noticable diffrences same as @TripleM-Dev.net ...   not sure if this analysis test walk through would help, but try to loop the selection on each category, then start stopwatch, then do the SetElementIds, then stop the stopwatch.

 

Debug.Writeline( each category how many milliseconds taken)

 

probably a specific category dragging the whole line. 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
Message 7 of 16

DanielKP2Z9V
Advocate
Advocate

@Moustafa_K ok, I'll try that. I've prompted chatGPT to write something like that, but haven't had chance to review it yet. Running it now in a 3d view to make sure it selects all elements (in case it's selecting by view - sorry, didn't have time to read it). It's processing right now, I will get back to you once/if it's done:

 

 

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;

namespace scripts
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class eirubrgeik : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiApp = commandData.Application;
            Document doc = uiApp.ActiveUIDocument.Document;

            // Collect all elements and group them by category name
            var allElements = new FilteredElementCollector(doc)
                              .WhereElementIsNotElementType()
                              .ToElements();

            var categories = allElements
                             .Where(e => e.Category != null)
                             .Select(e => e.Category.Name)
                             .Distinct();

            Stopwatch stopwatch = new Stopwatch();
            string results = "Timings for each category:\n\n";

            try
            {
                using (Transaction tx = new Transaction(doc))
                {
                    tx.Start("Process All Elements by Category");

                    foreach (var categoryName in categories)
                    {
                        stopwatch.Start();

                        // Collect elements of each specific category
                        var elementsInCategory = allElements
                                                 .Where(e => e.Category != null && e.Category.Name == categoryName)
                                                 .ToList();

                        stopwatch.Stop();

                        results += $"Category '{categoryName}' with {elementsInCategory.Count} elements: {stopwatch.ElapsedMilliseconds} ms\n";

                        stopwatch.Reset();
                    }

                    tx.Commit();
                }

                // Configure and show TaskDialog
                TaskDialog dialog = new TaskDialog("Detailed Timings");
                dialog.MainInstruction = "Performance Analysis Results";
                dialog.MainContent = results;
                dialog.AllowCancellation = true;
                dialog.CommonButtons = TaskDialogCommonButtons.Ok;
                dialog.ExpandedContent = "You can copy the results from this area. Press 'Ctrl + C' to copy.";
                dialog.FooterText = "Script executed successfully.";

                dialog.Show();
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return Result.Failed;
            }

            return Result.Succeeded;
        }
    }
}

 

0 Likes
Message 8 of 16

DanielKP2Z9V
Advocate
Advocate

@Moustafa_K oh cool, it was done before I finished writing a reply 😅. Here are the results - it doesn't look like there is any one category that's slowing it down - they all seem to take about a second.

 

 

 

[Window Title]
Add-In Manager (Manual Mode, Faceless) - Detailed Timings

[Main Instruction]
Performance Analysis Results

[Content]
Timings for each category:

Category 'Phases' with 2 elements: 1200 ms
Category 'Materials' with 374 elements: 1113 ms
Category 'Primary Contours' with 2 elements: 1120 ms
Category 'Area Schemes' with 3 elements: 1134 ms
Category 'Shared Site' with 3 elements: 1153 ms
Category 'Work Plane Grid' with 1399 elements: 1165 ms
Category 'Project Information' with 1 elements: 1138 ms
Category 'Structural Load Cases' with 8 elements: 1253 ms
Category 'Cameras' with 18 elements: 1249 ms
Category 'Section Boxes' with 18 elements: 1309 ms
Category 'Views' with 2839 elements: 1325 ms
Category 'Internal Origin' with 1 elements: 1328 ms
Category 'Schedules' with 627 elements: 1439 ms
Category 'Color Fill Schema' with 22 elements: 1404 ms
Category 'Sheets' with 410 elements: 1317 ms
Category 'HVAC Zones' with 1 elements: 1511 ms
Category 'HVAC Load Schedules' with 25 elements: 1355 ms
Category 'Building Type Settings' with 33 elements: 1367 ms
Category 'Space Type Settings' with 125 elements: 1393 ms
Category 'Survey Point' with 1 elements: 1332 ms
Category 'Project Base Point' with 1 elements: 1420 ms
Category 'Electrical Demand Factor Definitions' with 6 elements: 1444 ms
Category 'Electrical Load Classifications' with 7 elements: 1417 ms
Category 'Panel Schedule Templates - Branch Panel' with 3 elements: 1525 ms
Category 'Panel Schedule Templates - Data Panel' with 1 elements: 1342 ms
Category 'Panel Schedule Templates - Switchboard' with 1 elements: 1424 ms
Category 'Sun Path' with 2913 elements: 1361 ms
Category 'Electrical Load Classification Parameter Element' with 42 elements: 1498 ms
Category 'Pipe Segments' with 12 elements: 1375 ms
Category 'Material Assets' with 102 elements: 1385 ms
Category 'Legend Components' with 642 elements: 1410 ms
Category 'Levels' with 175 elements: 1371 ms
Category 'Walls' with 13402 elements: 1368 ms
Category 'Grids' with 32 elements: 1390 ms
Category 'Dimensions' with 4046 elements: 1471 ms
Category 'Windows' with 405 elements: 1371 ms
Category 'Doors' with 5253 elements: 1339 ms
Category 'Title Blocks' with 410 elements: 1290 ms
Category 'Floors' with 568 elements: 1422 ms
Category '<Sketch>' with 110722 elements: 1354 ms
Category '<Area Boundary>' with 5595 elements: 1402 ms
Category 'Areas' with 503 elements: 1426 ms
Category 'Constraints' with 409 elements: 1347 ms
Category 'Plan Region' with 4136 elements: 1300 ms
Category 'Automatic Sketch Dimensions' with 48410 elements: 1281 ms
Category 'Lines' with 26264 elements: 1402 ms
Category 'Spot Elevations' with 2507 elements: 1372 ms
Category 'Viewports' with 1402 elements: 1419 ms
Category 'Detail Groups' with 3242 elements: 1310 ms
Category 'Model Groups' with 2020 elements: 1388 ms
Category 'Railings' with 2237 elements: 1348 ms
Category 'Text Notes' with 4331 elements: 1476 ms
Category 'Detail Items' with 5660 elements: 1457 ms
Category 'Generic Models' with 3454 elements: 1402 ms
Category 'Elevations' with 45 elements: 1324 ms
Category '<Room Separation>' with 4279 elements: 1370 ms
Category 'Wall Sweeps' with 38 elements: 1406 ms
Category 'Balusters' with 9252 elements: 1469 ms
Category 'Schedule Graphics' with 529 elements: 1493 ms
Category 'Raster Images' with 40 elements: 1419 ms
Category 'Furniture' with 5106 elements: 1453 ms
Category 'Casework' with 2194 elements: 1456 ms
Category 'Plumbing Fixtures' with 2096 elements: 1431 ms
Category 'Curtain Panels' with 19 elements: 1349 ms
Category 'Curtain Wall Grids' with 19 elements: 1315 ms
Category 'Curtain Wall Mullions' with 79 elements: 1344 ms
Category 'Reference Planes' with 778 elements: 1443 ms
Category 'Shaft Openings' with 16 elements: 1387 ms
Category 'Revision Numbering Sequences' with 3 elements: 1379 ms
Category 'Rooms' with 4415 elements: 1427 ms
Category 'Room Tags' with 25576 elements: 1395 ms
Category 'Revision' with 13 elements: 1361 ms
Category 'Landscape Pla

 

 

 

hmm... it seems to have cut off the last few lines when I tried to copy them. Here's a screenshot of the last 30 or so lines:

DanielKP2Z9V_0-1714953546717.png

 

 

 

0 Likes
Message 9 of 16

ricaun
Advisor
Advisor

How many elements do you have in the document?

 

If you have 567000 elements and you are looping for each category like 100 categories.

 

The code is looping in each category and searching using Where in the 567000 elements every single category, that's the reason you have a similar time in each category, the element quantities is the same.


A better approach would be using Dictionary and group all the elements in the respective category, and the search for each element only gonna happen one time in the start.

 

Something like this:

 

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Diagnostics;
using System.Linq;

namespace RevitAddin.Commands
{
    [Transaction(TransactionMode.Manual)]
    public class CommandCategories : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
        {
            UIApplication uiapp = commandData.Application;

            UIDocument uidoc = uiapp.ActiveUIDocument;
            Document document = uidoc.Document;
            View view = uidoc.ActiveView;
            Selection selection = uidoc.Selection;

            // Collect all elements and group them by category name
            var allElements = new FilteredElementCollector(document)
                              .WhereElementIsNotElementType()
                              .ToElements();

            Stopwatch stopwatch = new Stopwatch();
            string results = "Timings for each category:\n\n";

            stopwatch.Start();

            var categoryElements = allElements
                            .Where(e => e.Category != null)
                            .GroupBy(x => x.Category.Name)
                            .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

            stopwatch.Stop();

            results += $"Dictionary with {categoryElements.Count} categories and {allElements.Count} elements: {stopwatch.ElapsedMilliseconds} ms\n";

            foreach (var item in categoryElements)
            {
                stopwatch.Restart();

                var categoryName = item.Key;
                var elementsInCategory = item.Value;

                selection.SetElementIds(elementsInCategory.Select(e => e.Id).ToList()); // Select elements in Revit

                results += $"Category '{categoryName}' with {elementsInCategory.Count} elements: {stopwatch.ElapsedMilliseconds} ms\n";

                stopwatch.Stop();
            }

            // Configure and show TaskDialog
            TaskDialog dialog = new TaskDialog("Detailed Timings");
            dialog.MainInstruction = "Performance Analysis Results";
            dialog.MainContent = results;
            dialog.AllowCancellation = true;
            dialog.CommonButtons = TaskDialogCommonButtons.Ok;
            dialog.ExpandedContent = "You can copy the results from this area. Press 'Ctrl + C' to copy.";
            dialog.FooterText = "Script executed successfully.";

            Console.WriteLine(results);

            dialog.Show();

            return Result.Succeeded;
        }
    }
}

 

 

I add the selection.SetElementIds in the loop for each category to see how long takes to select each category elements.

 

This is the time in the project sample Snowdon Towers Sample Architectural in Revit 2025

 

Timings for each category:

Dictionary with 139 categories and 34545 elements: 89 ms
Category 'Materials' with 220 elements: 3 ms
Category 'Views' with 326 elements: 5 ms
Category 'Primary Contours' with 2 elements: 0 ms
Category 'Area Schemes' with 2 elements: 0 ms
Category 'Phases' with 3 elements: 1 ms
Category 'Shared Site' with 2 elements: 0 ms
Category 'Work Plane Grid' with 201 elements: 2 ms
Category 'Revision' with 3 elements: 0 ms
Category 'Project Information' with 1 elements: 0 ms
Category 'Structural Load Cases' with 8 elements: 0 ms
Category 'Sun Path' with 438 elements: 3 ms
Category 'Internal Origin' with 1 elements: 0 ms
Category 'Color Fill Schema' with 9 elements: 0 ms
Category 'HVAC Zones' with 1 elements: 0 ms
Category 'HVAC Load Schedules' with 50 elements: 0 ms
Category 'Building Type Settings' with 33 elements: 0 ms
Category 'Space Type Settings' with 125 elements: 1 ms
Category 'Survey Point' with 1 elements: 0 ms
Category 'Project Base Point' with 1 elements: 2 ms
Category 'Electrical Demand Factor Definitions' with 9 elements: 0 ms
Category 'Electrical Load Classifications' with 15 elements: 0 ms
Category 'Panel Schedule Templates - Branch Panel' with 3 elements: 0 ms
Category 'Panel Schedule Templates - Data Panel' with 1 elements: 0 ms
Category 'Panel Schedule Templates - Switchboard' with 1 elements: 0 ms
Category 'Electrical Load Classification Parameter Element' with 90 elements: 0 ms
Category 'Material Assets' with 146 elements: 1 ms
Category 'Pipe Segments' with 11 elements: 0 ms
Category 'Legend Components' with 328 elements: 2 ms
Category 'Revision Numbering Sequences' with 2 elements: 0 ms
Category 'Sheets' with 55 elements: 0 ms
Category 'Title Blocks' with 55 elements: 0 ms
Category 'Reference Planes' with 1037 elements: 10 ms
Category 'Scope Boxes' with 3 elements: 0 ms
Category 'Lines' with 1184 elements: 10 ms
Category 'Dimensions' with 696 elements: 52 ms
Category 'Text Notes' with 335 elements: 234 ms
Category 'Schedules' with 92 elements: 1 ms
Category 'Detail Groups' with 61 elements: 2 ms
Category 'Array' with 6 elements: 1 ms
Category 'Constraints' with 280 elements: 8 ms
Category 'Callout Heads' with 1 elements: 98 ms
Category 'Generic Annotations' with 245 elements: 2 ms
Category 'Elevation Marks' with 36 elements: 0 ms
Category 'Room Tags' with 361 elements: 3 ms
Category 'Grid Heads' with 2 elements: 0 ms
Category 'Level Heads' with 2 elements: 0 ms
Category 'Revision Cloud Tags' with 1 elements: 0 ms
Category 'Section Marks' with 8 elements: 0 ms
Category 'Spot Elevation Symbols' with 2 elements: 0 ms
Category 'View Reference' with 1 elements: 0 ms
Category 'View Titles' with 1 elements: 0 ms
Category 'Levels' with 18 elements: 3 ms
Category 'Grids' with 28 elements: 1 ms
Category 'Cameras' with 36 elements: 0 ms
Category 'Section Boxes' with 36 elements: 0 ms
Category 'Walls' with 1128 elements: 18 ms
Category 'Stairs' with 27 elements: 3 ms
Category 'Runs' with 43 elements: 0 ms
Category 'Supports' with 2779 elements: 27 ms
Category 'Landings' with 17 elements: 2 ms
Category 'Stair Paths' with 360 elements: 2 ms
Category 'Railings' with 131 elements: 1 ms
Category '<Sketch>' with 3210 elements: 47 ms
Category 'Handrails' with 121 elements: 4 ms
Category 'Railing Rail Path Extension Lines' with 1195 elements: 12 ms
Category 'Multistory Stairs' with 3 elements: 2 ms
Category 'Top Rails' with 91 elements: 1 ms
Category 'Automatic Sketch Dimensions' with 1023 elements: 10 ms
Category 'Floors' with 191 elements: 337 ms
Category 'Slab Edges' with 68 elements: 1 ms
Category 'Doors' with 142 elements: 2 ms
Category 'Plan Region' with 40 elements: 0 ms
Category 'Divisions' with 10 elements: 0 ms
Category 'Parts' with 28 elements: 0 ms
Category 'Viewports' with 121 elements: 1 ms
Category 'Vertical Circulation' with 2 elements: 0 ms
Category 'Specialty Equipment' with 288 elements: 2 ms
Category 'Furniture' with 168 elements: 1 ms
Category 'Rectangular Straight Wall Opening' with 9 elements: 0 ms
Category 'Roofs' with 20 elements: 0 ms
Category 'Parking' with 20 elements: 0 ms
Category 'Shaft Openings' with 9 elements: 0 ms
Category 'Plumbing Fixtures' with 149 elements: 1 ms
Category 'Casework' with 177 elements: 1 ms
Category 'Generic Models' with 278 elements: 3 ms
Category 'Model Groups' with 49 elements: 16 ms
Category 'Site' with 75 elements: 10 ms
Category 'Windows' with 106 elements: 1 ms
Category 'Rooms' with 54 elements: 0 ms
Category '<Room Separation>' with 38 elements: 1 ms
Category 'Ramps' with 2 elements: 0 ms
Category '<Stair/Ramp Sketch: Run>' with 3 elements: 0 ms
Category '<Stair/Ramp Sketch: Riser>' with 6 elements: 0 ms
Category '<Stair/Ramp Sketch: Boundary>' with 22 elements: 0 ms
Category '<Stair/Ramp Sketch: Landing Center>' with 3 elements: 2 ms
Category 'Color Fill Legends' with 22 elements: 1 ms
Category 'Guide Grid' with 1 elements: 0 ms
Category '<Area Boundary>' with 628 elements: 5 ms
Category 'Areas' with 101 elements: 1 ms
Category 'Area Tags' with 101 elements: 0 ms
Category 'Elevations' with 15 elements: 0 ms
Category 'Detail Items' with 231 elements: 2 ms
Category 'Curtain Panels' with 681 elements: 6 ms
Category 'Curtain Wall Grids' with 235 elements: 2 ms
Category 'Curtain Wall Mullions' with 1425 elements: 14 ms
Category 'Raster Images' with 17 elements: 1 ms
Category 'Revision Clouds' with 2 elements: 0 ms
Category 'Spot Elevations' with 4 elements: 0 ms
Category 'Food Service Equipment' with 26 elements: 1 ms
Category 'Columns' with 118 elements: 1 ms
Category 'Planting' with 117 elements: 1 ms
Category 'Entourage' with 10 elements: 0 ms
Category 'Material Tags' with 65 elements: 0 ms
Category 'Balusters' with 237 elements: 7 ms
Category 'Lighting Fixtures' with 447 elements: 4 ms
Category 'Ceilings' with 68 elements: 1 ms
Category 'Wall Sweeps' with 258 elements: 2 ms
Category 'Design Option Sets' with 2 elements: 0 ms
Category 'Design Options' with 6 elements: 0 ms
Category 'Hardscape' with 10 elements: 0 ms
Category '<Stair/Ramp Sketch: Stair Path>' with 3 elements: 1 ms
Category 'Spot Slopes' with 194 elements: 2 ms
Category '<Path of Travel Lines>' with 95 elements: 54 ms
Category 'Path of Travel Tags' with 93 elements: 1 ms
Category 'Door Tags' with 251 elements: 11 ms
Category 'Wall Tags' with 1229 elements: 36 ms
Category 'Schedule Graphics' with 68 elements: 110 ms
Category 'Adaptive Points' with 2 elements: 0 ms
Category 'Window Tags' with 102 elements: 1 ms
Category 'Multi-Category Tags' with 36 elements: 9 ms
Category 'Parking Tags' with 20 elements: 3 ms
Category 'Planting Tags' with 54 elements: 2 ms
Category 'Cut Profile' with 5 elements: 5 ms
Category '<Insulation Batting Lines>' with 5 elements: 0 ms
Category 'Property Lines' with 1 elements: 2 ms
Category 'Property Line Segments' with 8 elements: 0 ms
Category 'Property Line Segment Tags' with 8 elements: 0 ms
Category 'Keynote Tags' with 3 elements: 0 ms
Category 'RVT Links' with 6 elements: 0 ms

 

 

Only 34k elements so is kinda fast.

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 10 of 16

DanielKP2Z9V
Advocate
Advocate

@ricaun thank you very much, that's very helpful. I've run it and here are the results. Many more elements and significant performance drop. It took about 10 minutes to complete. I've asked chatgpt to write this very readable awk snippet to sort the entries  in descending order. By the way I can't seem to copy all elements from this window, they got cut off after Revision again, but there were no outlier after that (as shown on the screenshot below).

 

I still don't see any single one category that would slow selection.SetElementIds or why it wouldn't affect native Revit's pickbox selection.

 

 

Category 'Lines' with 26264 elements: 117109 ms
Category 'Model Groups' with 2020 elements: 54876 ms
Category 'Levels' with 175 elements: 52072 ms
Category 'Shared Site' with 3 elements: 35572 ms
Category 'Detail Groups' with 3242 elements: 29835 ms
Category 'Walls' with 13402 elements: 28148 ms
Category '<Sketch>' with 110722 elements: 19698 ms
Category 'Plan Region' with 4136 elements: 13430 ms
Category 'Windows' with 405 elements: 12251 ms
Category 'Doors' with 5253 elements: 6327 ms
Category 'Furniture' with 5106 elements: 4604 ms
Category 'Plumbing Fixtures' with 2096 elements: 4505 ms
Category 'Viewports' with 1402 elements: 4250 ms
Category 'Generic Models' with 3454 elements: 3733 ms
Category '<Room Separation>' with 4279 elements: 3695 ms
Category 'Railings' with 2237 elements: 3626 ms
Category 'Automatic Sketch Dimensions' with 48410 elements: 3159 ms
Category 'Casework' with 2194 elements: 2518 ms
Category 'Floors' with 568 elements: 2387 ms
Category 'Balusters' with 9252 elements: 1921 ms
Category 'Dimensions' with 4046 elements: 1919 ms
Category 'Detail Items' with 5660 elements: 1740 ms
Category 'Room Tags' with 25576 elements: 1687 ms
Category 'Rooms' with 4415 elements: 1674 ms
Category 'Views' with 2839 elements: 1317 ms
Category 'Wall Sweeps' with 38 elements: 1267 ms
Category 'Reference Planes' with 778 elements: 1076 ms
Category 'Shaft Openings' with 16 elements: 948 ms
Category 'Grids' with 32 elements: 890 ms
Category '<Area Boundary>' with 5595 elements: 813 ms
Category 'Title Blocks' with 410 elements: 319 ms
Category 'Spot Elevations' with 2507 elements: 315 ms
Category 'Text Notes' with 4331 elements: 212 ms
Category 'Legend Components' with 642 elements: 208 ms
Category 'Constraints' with 409 elements: 184 ms
Category 'Cameras' with 18 elements: 142 ms
Category 'Phases' with 2 elements: 141 ms
Category 'Elevations' with 45 elements: 134 ms
Category 'Schedule Graphics' with 529 elements: 132 ms
Category 'Curtain Panels' with 19 elements: 131 ms
Category 'Curtain Wall Grids' with 19 elements: 128 ms
Category 'Work Plane Grid' with 1399 elements: 110 ms
Category 'Section Boxes' with 18 elements: 103 ms
Category 'Areas' with 503 elements: 95 ms
Category 'Revision' with 13 elements: 75 ms
Category 'Sun Path' with 2913 elements: 73 ms
Category 'Revision Numbering Sequences' with 3 elements: 60 ms
Category 'Sheets' with 410 elements: 51 ms
Category 'Schedules' with 627 elements: 50 ms
Category 'Area Schemes' with 3 elements: 49 ms
Category 'Raster Images' with 40 elements: 47 ms
Category 'Primary Contours' with 2 elements: 46 ms
Category 'Material Assets' with 102 elements: 45 ms
Category 'Curtain Wall Mullions' with 79 elements: 44 ms
Category 'Electrical Load Classification Parameter Element' with 42 elements: 42 ms
Category 'Panel Schedule Templates - Branch Panel' with 3 elements: 41 ms
Category 'Electrical Load Classifications' with 7 elements: 40 ms
Category 'Electrical Demand Factor Definitions' with 6 elements: 39 ms
Category 'Building Type Settings' with 33 elements: 37 ms
Category 'Project Base Point' with 1 elements: 21 ms
Category 'Internal Origin' with 1 elements: 16 ms
Category 'Panel Schedule Templates - Data Panel' with 1 elements: 14 ms
Category 'Survey Point' with 1 elements: 13 ms
Category 'Panel Schedule Templates - Switchboard' with 1 elements: 12 ms

 

 

awk:

 

awk '{
    time = $(NF-1);  # Extract the time in milliseconds (second last field)
    data[time] = $0  # Map each line to its corresponding time key
}
END {
    for (time in data) times[++n] = time;  # Collect all times for sorting
    n = asort(times);  # Sort times numerically
    for (i = n; i >= 1; i--)  # Loop in reverse order for descending sort
        print data[times[i]];  # Print lines in sorted order of time, descending
}' Untitled.txt

 

 rest of the results:

DanielKP2Z9V_0-1714953207145.png

 

0 Likes
Message 11 of 16

ricaun
Advisor
Advisor

What do you mean by native Revit's pickbox selection?

 

You probably should try and test in some Revit sample, so is easier to compare.

 

What exactly is your goal to selecting elements by category? 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 12 of 16

DanielKP2Z9V
Advocate
Advocate

> You probably should try and test in some Revit sample, so is easier to compare.

 

That's a good point, I've run it on Snowdon Towers Sample Architectural in Revit 2024 and interestingly enough got very different results...

 

Category 'Levels' with 18 elements: 5842 ms
Category 'Walls' with 1128 elements: 4295 ms
Category 'Supports' with 2779 elements: 3974 ms
Category 'Shared Site' with 2 elements: 3315 ms
Category '<Sketch>' with 3210 elements: 3011 ms
Category 'Model Groups' with 49 elements: 2117 ms
Category 'Floors' with 191 elements: 2100 ms
Category 'Reference Planes' with 1037 elements: 1898 ms
Category '<Room Separation>' with 38 elements: 1541 ms
Category 'Scope Boxes' with 3 elements: 1462 ms
Category 'Doors' with 142 elements: 1145 ms
Category 'Shaft Openings' with 9 elements: 1104 ms
Category 'Windows' with 106 elements: 999 ms
Category 'Stairs' with 27 elements: 872 ms
Category 'Runs' with 43 elements: 863 ms
Category 'Wall Sweeps' with 258 elements: 855 ms
Category 'Ceilings' with 68 elements: 805 ms
Category 'Grids' with 28 elements: 740 ms
Category 'Specialty Equipment' with 288 elements: 739 ms
Category 'Roofs' with 20 elements: 727 ms
Category 'Landings' with 17 elements: 712 ms
Category 'Railing Rail Path Extension Lines' with 1195 elements: 646 ms
Category 'Columns' with 118 elements: 618 ms
Category 'Rectangular Straight Wall Opening' with 9 elements: 490 ms
Category 'Rooms' with 54 elements: 465 ms
Category 'Lighting Fixtures' with 447 elements: 413 ms
Category 'Railings' with 131 elements: 347 ms
Category 'Curtain Wall Grids' with 235 elements: 320 ms
Category 'Slab Edges' with 68 elements: 313 ms
Category 'Lines' with 1184 elements: 308 ms
Category 'Curtain Panels' with 681 elements: 289 ms
Category 'Multistory Stairs' with 3 elements: 243 ms
Category 'Views' with 326 elements: 219 ms
Category 'Detail Groups' with 61 elements: 171 ms
Category 'Text Notes' with 335 elements: 163 ms
Category 'Plan Region' with 40 elements: 110 ms
Category 'Detail Items' with 231 elements: 108 ms
Dictionary with 139 categories and 34509 elements: 99 ms
Category 'Dimensions' with 696 elements: 89 ms
Category 'Wall Tags' with 1229 elements: 88 ms
Category 'Automatic Sketch Dimensions' with 1023 elements: 85 ms
Category 'Schedule Graphics' with 68 elements: 84 ms
Category 'Constraints' with 280 elements: 77 ms
Category 'Site' with 75 elements: 61 ms
Category '<Stair/Ramp Sketch: Boundary>' with 22 elements: 60 ms
Category 'Callout Heads' with 1 elements: 55 ms
Category 'Planting' with 117 elements: 51 ms
Category 'Curtain Wall Mullions' with 1425 elements: 48 ms
Category 'Viewports' with 121 elements: 47 ms
Category 'Balusters' with 237 elements: 43 ms
Category 'Door Tags' with 251 elements: 41 ms
Category 'Plumbing Fixtures' with 149 elements: 36 ms
Category 'Areas' with 101 elements: 31 ms
Category '<Stair/Ramp Sketch: Landing Center>' with 3 elements: 29 ms
Category '<Stair/Ramp Sketch: Stair Path>' with 3 elements: 28 ms
Category 'RVT Links' with 6 elements: 27 ms
Category 'Food Service Equipment' with 26 elements: 24 ms
Category 'Room Tags' with 361 elements: 20 ms
Category 'Casework' with 177 elements: 19 ms
Category 'Cameras' with 36 elements: 18 ms
Category 'Elevations' with 15 elements: 16 ms
Category 'Generic Models' with 278 elements: 14 ms
Category 'Spot Slopes' with 194 elements: 12 ms
Category 'Sun Path' with 438 elements: 11 ms
Category 'Multi-Category Tags' with 36 elements: 10 ms
Category 'Material Tags' with 65 elements: 7 ms
Category 'Path of Travel Tags' with 93 elements: 6 ms
Category 'Cut Profile' with 5 elements: 5 ms
Category 'Planting Tags' with 54 elements: 4 ms
Category 'Hardscape' with 10 elements: 3 ms
Category 'Property Lines' with 1 elements: 2 ms
Category 'Keynote Tags' with 3 elements: 1 ms
Category 'Property Line Segment Tags' with 8 elements: 0 ms

 

I've updated the script just to display results in Textbox instead of TaskDialog (I couldn't copy them for some reason): using Autodesk.Revit.Attributes;using Autodesk.Revit.DB;using Autodesk.Revit - Pastebin.com

 

What do you mean by native Revit's pickbox selection?

When a user draws a selection window in the viewport to select multiple elements (click and dragging on the viewport). Sorry, I'm not sure what a correct term is.

 

> What exactly is your goal to selecting elements by category? 

 

I'm trying to assign to "ctrl a" keybinding "select all elements in the viewport" command. However, it's often less practical when it's in fact faster just to draw a selection window in the usual way. Selecting elements by category  test was suggested to check if there wasn't one category slowing selection.setElementIds method down.

 

 

 

0 Likes
Message 13 of 16

ricaun
Advisor
Advisor

The time to select 18 Level looks terrible for some reason.

 

Maybe is your Revit or some plugin messing with the selection.

 

I recreate the Command to copy the results to the Clipboard and order by time.

 

I tested with Revit 2024 - 24.0.4.427:

Project: Snowdon Towers Sample Architectural - 24.0.4.427 - Cover
Dictionary with 139 categories and 34509 elements: 109 ms

Category 'Floors' with 191 elements: 407 ms
Category 'Text Notes' with 335 elements: 270 ms
Category 'Schedule Graphics' with 68 elements: 115 ms
Category 'Callout Heads' with 1 elements: 110 ms
Category '<Path of Travel Lines>' with 95 elements: 50 ms
Category 'Wall Tags' with 1229 elements: 31 ms
Category 'Supports' with 2779 elements: 28 ms
Category '<Sketch>' with 3210 elements: 26 ms
Category 'Dimensions' with 696 elements: 18 ms
Category 'Model Groups' with 49 elements: 16 ms
Category 'Walls' with 1128 elements: 15 ms
...

 You should try with a different Revit version, like 2025.

Have no idea the reason is so bad in your case, could be your computer as well 😅

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 14 of 16

DanielKP2Z9V
Advocate
Advocate

I've tried disabling all addons and run the test again on the Snowdon project with the same Revit 2024, but it yielded the same results: Project: Snowdon Towers Sample Architectural - 24.2.10.64 - CoverDictionary wi - Pastebin.com

 

I've tried running it in Revit 2019 on the RAC_basic_sample_project and it yielded better results: Project: RAC_basic_sample_project - 20190108_1515(x64) - Title SheetDictionary - Pastebin.com

 

Then tried again in Revit 2019 on one of our bigger projects (117799 elements) and it still have good results:

Dictionary with 109 categories and 117799 elements: 405 msCategory 'Schedule - Pastebin.com

 

So 2019 seems to be faster on a bigger model than 2024 without plugins on a smaller model. Do you know what else might be causing it or some of other way to profile this behavior?

 

>  You should try with a different Revit version, like 2025.

Good point, I didn't have 2025 installed yet, only 2019. We wouldn't be able to switch to 2025 yet anyway.

0 Likes
Message 15 of 16

TripleM-Dev.net
Advisor
Advisor

Hi @DanielKP2Z9V,

 

The iteration for all found categories on the allElements actually slows it down, not the actual selecting.

I've tried this code, with the transaction it takes a while (a min or so), without the transaction I cancelled it after 3min.

This is on Win10, Revit 2022, and a model with in total 90K elements (ca. 40k annotation elements) and open 3D view of whole model

 

I Changed the code with SetElementId and it ran 21sec, and as I now see similar solution as @ricaun , using groupBy on the initial elements. I directly used the Igrouping list and @ricaun converted first to a dictionary (If I would use the data further in a addin I also would convert it to a dictionary.

 

Sample Code:

 

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;

namespace scripts
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class eirubrgeik : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiApp = commandData.Application;
            Document doc = uiApp.ActiveUIDocument.Document;
            UIDocument uidoc = uiApp.ActiveUIDocument;

            // Collect all elements and group them by category name
            var allElements = new FilteredElementCollector(doc).WhereElementIsNotElementType().ToElements(); //For actual selection in view also use View.id argument.

            string results = "Timings for initial Grouping:\n\n";
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            IEnumerable<IGrouping<string,  Element>> GroupedData =  allElements.Where(e => e.Category != null).GroupBy(e => e.Category.Name);

            stopwatch.Stop();
            results += $"Grouping duration: '{stopwatch.ElapsedMilliseconds} ms, with {GroupedData.Count()} Categories\n";


            try
            {
                int totalElements = 0;
                stopwatch.Start();
                results += $"Timings for each category:\n\n";
                foreach (IGrouping<string, Element> GroupData in GroupedData)
                {
                    totalElements += GroupData.Count();
                    results += $"Category '{GroupData.Key}' with {GroupData.Count()} elements\n";

                    uidoc.Selection.SetElementIds(GroupData.Select(e => e.Id).ToList()); // Added line for second test with selecting the elements

                }

                stopwatch.Stop();
                results += $"Retrieving Results: '{stopwatch.ElapsedMilliseconds} ms, with {totalElements} elements total.\n";

                System.Windows.Forms.MessageBox.Show(results);
                 
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return Result.Failed;
            }

            return Result.Succeeded;
        }
    }
}

 

 

Results without SetElementIds (removed several categories in data below):

- First the number of categories found (GroupBy, IGrouping items)

- Next the category element count (no timer include here)

- At end the total number of items processed and total time for the loop

 

Timings for initial Grouping:

Grouping duration: '0 ms, with 112 Categories
Timings for each category:

Category 'Levels' with 8 elements
Category 'Views' with 824 elements
Category 'Elevations' with 105 elements
Category 'Primary Contours' with 2 elements
Category 'Area Schemes' with 7 elements
Category 'Phases' with 2 elements
Category 'Shared Site' with 3 elements
Category 'Work Plane Grid' with 510 elements
Category 'Project Information' with 1 elements
Category 'Structural Load Cases' with 8 elements
Category 'Internal Origin' with 1 elements
......
Category 'Structural Foundations' with 1 elements
Category 'Analytical Isolated Foundations' with 1 elements
Category 'Ceiling Tags' with 1 elements
Category 'Parkeren_20220621.dwg' with 1 elements
Category 'Revision' with 5 elements
Category 'Top Rails' with 27 elements
Category 'Railing Rail Path Extension Lines' with 57 elements
Category 'Rectangular Straight Wall Opening' with 2 elements
Category 'Revision Numbering Sequences' with 2 elements
Retrieving Results: '408 ms, with 92813 elements total.

 

 

And With SetElementId:

 

---------------------------

---------------------------
Timings for initial Grouping:

Grouping duration: '0 ms, with 112 Categories
Timings for each category:

Category 'Levels' with 8 elements
Category 'Views' with 824 elements
Category 'Elevations' with 105 elements
Category 'Primary Contours' with 2 elements
.....
Category 'Railing Rail Path Extension Lines' with 57 elements
Category 'Rectangular Straight Wall Opening' with 2 elements
Category 'Revision Numbering Sequences' with 2 elements
Retrieving Results: '21577 ms, with 92813 elements total.

---------------------------
OK   
---------------------------

 

 

0 Likes
Message 16 of 16

TripleM-Dev.net
Advisor
Advisor

Are we now beyond the inital request? -> Selecting all elements in view but SetElementsIds is 2x as slow as manual selection.

 

First some optimalization can be found in how the elements are gathered, and exclude elements the user normally can't select in the UI, to simulate the UI selection content.

 

This can completely be done by applying filters on the FilteredElementCollector

First would be to exclude all elements in groups (can be done by GroupId == ElementId.Invalid)

Next would be to use a inverted mulicategory filter to deselect categories like: Sketch lines, Constraint dimensions etc.

 

But all of this actually depends on, why a User needs to select all elements visible in a view (manually or by API)

what's the goal, what happens after the selection?

 

- Michel

0 Likes