[Test] defn.count_instances vs defn.instances.lenght
-
I was curious of why there was a method
definition.count_instances
- as I've often just useddefinition.instances.length
. Did a quick test:d=Sketchup.active_model.definitions[0]; c=1000; puts "Counting #{d.count_instances} instances..."; t=Time.now; c.times { d.count_instances }; puts "Count: #{Time.now-t}s"; t=Time.now; c.times { d.instances.length }; puts "Count: #{Time.now-t}s";
Counting 8642 instances... Count: 0.0s Count: 1.748s
Significant difference.
In order to get.count_instances
to be of notisable lag I needed to go over 1,000,000 iterations ( 0.38s). With 10,000,000 it took 3.678s. I did not even try to test withdefinition.instances.length
with that many iterations. -
Reason: The count_instances method queries the C++ side for an integer.
Each time you call the instances method, the C side API has to allocate a Ruby Array object which has as it's members, pointers to all the definition's C++ instances collection.
Your test might get closer if you have a statement like i=defn.instances outside the loop. Ie, create the Array only once, then have i.length inside the loop's block.
If you do not need a Ruby Array, then count_instances should always be faster.
This is a candidate for the Optimization topic.
-
Duh! Should off course have eliminated new object creations. (They are all too expensive.)
Changing it and the numbers are quite different:
d=Sketchup.active_model.definitions[0]; inst=d.instances; c=10000000; puts "Counting #{d.count_instances} instances..."; t=Time.now; c.times { d.count_instances }; puts "Count: #{Time.now-t}s"; t=Time.now; c.times { inst.length }; puts "Count: #{Time.now-t}s"
Counting 8642 instances... Count: 3.562s Count: 1.795s
Advertisement