Why is add_arc so slow?

We are creating a plugin to export AutoCAD dwg and draw it on SketchUp. There are many shapes to draw and it is really time consuming for large dwg files.

I tested add_arc with the code:

model = Sketchup.active_model
entities = model.active_entities

vector = Geom::Vector3d.new 0,0,1
vector2 = Geom::Vector3d.new 1,0,0
vector3 = vector.normalize!

t1 = Time.now

(1..3000).each {|x|
  centerpoint = Geom::Point3d.new(0, x*5, 0)
  edges = entities.add_arc centerpoint, vector2, vector3, 10, 15.degrees, 135.degrees
}

t2 = Time.now
puts "time: #{t2-t1}\n"

It took 20 seconds.

I saved it as a skp file. Then SketchUp loaded the skp immediately. I was wondering why add_arc was so slow and loading the same model was so much quick? Any way to speed up the drawing tons of shapes with Ruby api?

The #start_operation method is used to notify SketchUp that a new operation (which can be undone) is starting… It is recommended to always set disable_ui to true .

Usually this will significantly speed it up…
e.g.:

.
model.start_operation("Add arcs", true)
(1..3000).each {|x|
  centerpoint = Geom::Point3d.new(0, x*5, 0)
  edges = entities.add_arc centerpoint, vector2, vector3, 10, 15.degrees, 135.degrees
}
model.commit_operation
.
2 Likes

Thanks @dezmo . I added model.start_operation as what your said. It reduced a few seconds indeed, but not much. I tried 3 times, the results were 17, 23, and 19 seconds. Not significantly improving. Weird.

Is there any validity check in processing add_arc to slow down the drawing? Why is skp loading quickly? I thought they were the similar processes to show models out.

SketchUp will try to automatically merge and intersect geometry added. This leads to increasing time to add a new entity that is proportional to how much geometry is already in the Entities collection you are adding to.

The entities.add_* methods acts much like the native tools in that respect. The native tools add entities one by one and in that scenario this auto-merge isn’t particularly noticeable to the user.

But for bulk generation it’s an issue. That’s why we added the EntitiesBuilder interface recently. It puts more responsibility on the API use to craft a valid model (no overlapping vertices/edges/face). In return it’s significantly faster.

At the moment the interface doesn’t support arcs. I’d recommend you submit a feature request for that: Issues · SketchUp/api-issue-tracker · GitHub

Opening a SketchUp model only reads the data - that scenario never needs to perform any marge/intersect logic - hence it doesn’t compare in performance. (Creating geometry will always have more overhead than simply reading serialized data - as you have to perform data sanity checks when you create geometry.)

3 Likes

On my machine (Win10 i7-8750H 2.2GHz Nvidia GTX1060) and adding the 3000 arcs into a new group I am seeing consistently around 9.5 - 9.7 seconds.

What are the specs of the machine you are testing upon?

Adding to a new group means that the arcs will only need to be checked with their siblings for geometry merging, and not the rest of the model. The group can always be exploded at the end of the operation.

def go
  model = Sketchup.active_model
  entities = model.active_entities

  model.start_operation("Add arcs", true)
    t1 = Time.now
    grp = entities.add_group
    ents = grp.entities
    (1..3000).each { |x|
      ents.add_arc(
        Geom::Point3d.new(0, x*5, 0),
        X_AXIS, Z_AXIS, 10, 15.degrees, 135.degrees
      )
    }
    t2 = Time.now
  model.commit_operation
  puts "time: #{t2.to_f-t1.to_f}\n"
end

Note in the above example, I’ve removed the assignments of the vectors and used the global constants X_AXIS and Z_AXIS. I also removed the unnecessary reference assignments from inside the each loop as these assignments are not really used later and they just eat time creating Ruby object references.


P.S. - In your post please fixed the code block. See: