Performance problem with SUEntitiesAddGroup

We have a problem concerning the performance of the SUEntitiesAddGroup function. When we are writing an average sized sketchup file of about 14MB, to which about 1500 groups have been added by this function, then this export takes about 60 seconds and a performance analysis shows that 98% of the time are used by this function.
Also, a large part of the time in this function is used by _towupper_l, a character conversion function.

Is there anything I could do to avoid this problem? In the moment this is our main performance bottleneck.

@bugra, @paul - is this similar to the issue with anti-virus applications that might slow this down?

We did get some reports of Virus Scanners slowing down some of our operations but we never could duplicate it.
This case might be different though. Adding groups require generation of component definitions with unique names and we may have an actual bottleneck there. Is this on a Mac ? Would you happen to have a simple program duplicating it?
Thanks!

We are working with Windows. Here is an simple win32 console application showing the problem:

#include "stdafx.h"

#include <crtdbg.h>
#include <slapi/initialize.h>
#include <slapi/model/model.h>
#include <slapi/model/entities.h>
#include <slapi/model/face.h>
#include <slapi/model/vertex.h>
#include <slapi/model/group.h>

#define SUCheck(command) {SUResult res=command;_ASSERT(res==SU_ERROR_NONE);res;}

int _tmain(int argc, _TCHAR* argv[])
{
   SUInitialize();

   SUGeometryInputRef geomRef = SU_INVALID;
   SUModelRef modelRef = SU_INVALID;

   SUCheck(SUModelCreate(&modelRef));

   SUEntitiesRef entities = SU_INVALID;
   SUCheck(SUModelGetEntities(modelRef, &entities));

   for(unsigned int i=0;i<1000;i++)
   {
      SUGroupRef groupRef = SU_INVALID;
      SUCheck(SUGroupCreate(&groupRef));

      SUCheck(SUEntitiesAddGroup(entities,groupRef));


      SUGeometryInputRef geomInputRef = SU_INVALID;
      SUCheck(SUGeometryInputCreate(&geomInputRef));
      SUPoint3D p0 = {0.,0.,0.};
      SUCheck(SUGeometryInputAddVertex(geomInputRef,&p0));
      SUPoint3D p1 = {i,10,0.};
      SUCheck(SUGeometryInputAddVertex(geomInputRef,&p1));
      SUPoint3D p2 = {i,0.,10.};
      SUCheck(SUGeometryInputAddVertex(geomInputRef,&p2));
      
      SULoopInputRef loopRef = SU_INVALID;
      SUCheck(SULoopInputCreate(&loopRef));

      SUCheck(SULoopInputAddVertexIndex(loopRef, 0));
      SUCheck(SULoopInputAddVertexIndex(loopRef, 1));
      SUCheck(SULoopInputAddVertexIndex(loopRef, 2));

      SUCheck(SUGeometryInputAddFace(geomInputRef,&loopRef,0));

      SUEntitiesRef groupEntities = SU_INVALID;
      SUCheck(SUGroupGetEntities(groupRef, &groupEntities));

      SUCheck(SUEntitiesFill(groupEntities,geomInputRef,true));

      SUCheck(SUGeometryInputRelease(&geomInputRef));
   }

   SUCheck(SUModelRelease(&modelRef));
   SUTerminate();

    return 0;
}

This program runs about 20 seconds on my PC and about 88% of the time is spent in SUEntitiesAddGroup
And if I add not only 1000 but 2000 groups, this goes up to 120 seconds and 96%.

I’ve run into this problem as well and it’s a rather bizarre performance quirk. For example, the following Ruby code creates 1000 groups in 25s on my computer

mod = Sketchup.active_model 
ent = mod.entities 

t0 = Time.now
1.times do
  ng = ent.add_group
  1000.times do
    g = ng.copy
    g.entities.add_line [0, 0, 0], [Random::rand * 20 - 10, Random::rand * 20 - 10, Random::rand * 20 - 10]
  end
end
t1 = Time.now
puts 'Done '+(t1 - t0).to_s + 's'

However, if you change the loops from 1, 1000 to 32, 32 (~sqrt 1000) the script runs about 10 times faster. The code below creates 1024 groups in 2.4s.

mod = Sketchup.active_model 
ent = mod.entities 

t0 = Time.now
32.times do
  ng = ent.add_group
  32.times do
    g = ng.copy
    g.entities.add_line [0, 0, 0], [Random::rand * 20 - 10, Random::rand * 20 - 10, Random::rand * 20 - 10]
  end
end
t1 = Time.now
puts 'Done '+(t1 - t0).to_s + 's'

I don’t know if this is a Ruby only thing but it’s probably worth a try.

1 Like

That’s strange. I saw ~30 and ~15 secs when I ran your snippets.
If I wrapped it all up in start/commit_operation I saw ~20s and ~2.5s.

Good cases for profiling tests!