ModelDoc2 Lock degrades performance

Is ModelDoc2::LockModel supposed to increase performance? I’m running some benchmarks, and I am noticing it is doing the opposite.

  public class Example
  {
      public static void Run()
      {
          var solidworksManager = new SOLIDWORKSInstanceManager();
          var swApp = solidworksManager.GetNewInstance("", SOLIDWORKSInstanceManager.Year_e.Latest, 160);
          swApp.Visible = true;

          var currentLocation = (new FileInfo(typeof(Example).Assembly.Location)).Directory;
          var testFile = currentLocation.GetFiles()
              .FirstOrDefault(x => x.Name.Equals("tank_20lb_propane_&.SLDPRT", StringComparison.OrdinalIgnoreCase));

          if (testFile == null)
              throw new FileNotFoundException("Could not find 'tank_20lb_propane_&.SLDPRT' in the current directory.");

          string filePath = testFile.FullName;

          // Open the file
          int errors = 0, warnings = 0;
          var swModel = swApp.OpenDoc6(filePath,
                                       (int)swDocumentTypes_e.swDocPART,
                                       (int)swOpenDocOptions_e.swOpenDocOptions_Silent,
                                       "", ref errors, ref warnings);

          if (swModel == null)
              throw new InvalidOperationException("Failed to open the document.");

          // Scenario 1: LockModel = true
          Console.WriteLine("Starting Scenario 1 (LockModel = true)");
          MeasureSelectionTime(swModel, true);


          swModel.ClearSelection();

          Console.WriteLine("\n-----------------------------------------------\n");

          // Scenario 2: LockModel = false
          Console.WriteLine("Starting Scenario 2 (LockModel = false)");
          MeasureSelectionTime(swModel, false);

          swApp.CloseDoc(swModel.GetTitle());
          swApp.ExitApp();

          Console.WriteLine("\nPress any key to exit...");
          Console.ReadKey();
      }

      private static void MeasureSelectionTime(ModelDoc2 swModel, bool lockModel)
      {
          var swFeature = (Feature)swModel.FirstFeature();

          var ModelView = swModel.ActiveView as ModelView;

          if (lockModel)
              swModel.Lock();

          var stopwatch = System.Diagnostics.Stopwatch.StartNew();

          var rootItem = swModel.FeatureManager.GetFeatureTreeRootItem2((int)swFeatMgrPane_e.swFeatMgrPaneBottom);
          TraverseTreeItems(rootItem);

          stopwatch.Stop();

          if (lockModel)
              swModel.UnLock();

          Console.WriteLine($"Total Selection Time (LockModel={lockModel}): {stopwatch.ElapsedMilliseconds} ms");
      }








      public static void PrintComponentsFlat(ModelDoc2 swModel)
      {
          Console.WriteLine("Method 1: Flat List using GetComponents");
          var swAssembly = swModel as AssemblyDoc;

          if (swAssembly == null)
              return;
          var comps = swAssembly.GetComponents(false) as object[];
          foreach (Component2 comp in comps)
              Console.WriteLine(comp.Name2);
      }
      // Method 2: Recursive Hierarchical Traversal using GetFeatureTreeRootItem
      public static void TraverseTreeItems(TreeControlItem item, string indent = "")
      {
          while (item != null)
          {
              Console.WriteLine($"{indent}{item.Text}");

              var child = item.GetFirstChild();
              if (child != null)
                  TraverseTreeItems(child, indent + "  ");

              item = item.GetNext();
          }
      }





      static void TraverseFeatureForComponents(Feature swFeature, Action<Component2> performAction)
      {
          var swSubFeature = default(Feature);

          var swComponent = swFeature.GetSpecificFeature2() as Component2;
          if (swComponent != null)
          {
              performAction(swComponent);

              swSubFeature = swComponent.FirstFeature();
              while (swSubFeature != null)
              {
                  TraverseFeatureForComponents(swSubFeature, performAction);
                  swSubFeature = swSubFeature.GetNextFeature() as Feature;
              }
          }


      }

  }

To clone repo here: SW_API_Tips_Tricks/LockModel/LockModel at master · BlueByteSystemsInc/SW_API_Tips_Tricks · GitHub

Just traversing the tree already takes 300 ms? Damn. Is this out-of-process?

In my testing, locking was about 20% faster.

Lock prevents all the tool bar refreshes from running so it does reduce resources consumed by SolidWorks however it is primarily used to prevent the user from unexpectedly interacting with something that may disrupt the intended API activity while I’m not surprised it didn’t positively affect your test I am a bit surprised it added time, however, how much of the additional time was involved in calling Lock and Unlock? Make sure you Unlock in a Try Finally statement though so you don’t leave the user unable to do anything in the event an exception is raised.

I think the bigger performance calls are these however I doubt they would have any impact on your test being a ReadOnly operation.

EnableGraphicsUpdate = False and EnableFeatureTree = False

I have in the past tested traversal code in and out of process and in process is orders of magnitude faster even with all of the various performance options in play.