To clarify, to_a does a shallow copy/conversion it does not clone the objects referenced by the collection. What it does though is give a flat structure (an Array) that is not at risk of breaking if you modify it while iterating.
Nope. Just SU and my script editor (Brackets). On a Mac btw.
OK, strange… If I create a timer for this script to run, I ALSO get about 2.5 seconds
BUT Then I cannot use Sketchup for about 45 seconds while (as happens on a Mac) a spinning rainbow colored disc replaces the cursor.
To me, this suggests this is some background memory re-allocation going on? Not sure what else to think. Any ideas?
2.5 seconds is slightly faster than the times I was getting on a 3.46GHz processor here, so there’s something else going on after that method has finished.
I haven’t heard of your Brackets editor before. Just to eliminate it, try quiting it and just pasting that method into the Ruby console in SketchUp and calling it from the console.
Is the method you posted your whole extension? Is there something else running after this method that could cause a delay?
Are there any other extensions installed that could be conflicting, maybe some using observers?
In Activity Monitor look at Swap used in the Memory tab; or top in terminal check for swapins/swapouts; or whatever you normally use to see if it is the use of virtual memory that is slowing your Mac down. How much RAM do you have? Is it full?
Unloaded all my plugins, closed all other programs, ran script from Ruby Console… still the same thing. Operation completes in about 2.5 to 2.8 seconds then hangs afterward. I looked at Activity Monitor and, while I’m not sure about swapins/swapouts, I did notice that the memory usage in this “afterward” period starts at about 120 MB and continues to jump upward by about 25MB increments until it peaks at 440 MB when SU finally begins to react again. Seems curious.
I have 8 gig of RAM, 3.4 of which is allocated when I start this operation and 4.5 when complete. Swap Memory stays at Zero.
These two mean the same thing. I just wondered if it was swapping out to disk, which would slow things down. It doesn’t seem to be doing that, so I don’t know how to help, sorry.
I tried putting it inside a model.start_operation("",true) / model.commit_operation block and I actually got longer times which I’ve never seen before. It’s usually faster when you set disable_ui = true. I got about 2.6 without and 3.5 with the start/commit.
No one suggested otherwise, certainly not I.
Nor is a “deep” copy necessary. In fact a deep copy would work against the task at hand, because the original objects are what the code wishes to act upon.
The “first rule of iteration” is not magical or complicated at all. It is simply a copy of all of the references, that does not change during the iteration. Meaning it keeps the same number of items throughout the life of the iterative loop. It is not necessary to even shift or pop references out of the iterative array. But it is smart to test each member for validity at each step. This means that there might be operations that cause the reference that before was pointing at something both valid and non-nil, but might have been destroyed becoming a “
Sketchup::DeletedEntity” object or the reference might point at
#to_a Enumerable method comes from Ruby, and Ruby itself has no idea what SketchUp’s classes are, nor how to create them unless told how via special methods (
#initialize_dup ) that the API has never implemented. Therefore Ruby wouldn’t know how to make a “deep” copy of a SketchUp collection (or array) anyway.
This is emphasized by the fact that SketchUp’s Entity classes are actually created on the C++ side of things, and not by the standard Ruby constructor methods (
#initialize.) Instead we coders ask SketchUp’s API for Entity subclass objects via factory methods that are implemented upon the
Sketchup::Entities collection object.
Secondly, you will always interact with Ruby objects via a reference that points at the object held by the C-side.
Incorrect. You are just sowing confusion here.
When you iterate an array copy you are iterating this copy. Plain and simple.
The whole point of it being a copy is that it shares the same references that the original collection shares.
It needs to have the same references, because the code needs to act upon the same objects that those references are pointing at.
So when an iterative loop iterates an array using the references and acting upon them or having them interact in destructive ways, the original collection changes … which is the expectation, … you need to be interacting with an array / collection that will not change despite some of it’s members perhaps becoming invalid or nil. This is acceptable because we can check items as we iterate.
So we use a “snapshot” copy so that the number of items does not change, nor the order of items change, throughout the loop. We do this because when items change in a C++ side collection, (or are removed,) we cannot trust that the items will remain in the same order in that collection.
At the end of the loop, the old array copy “snapshot” is no longer useful and is discarded, whether or not it’s references point at nothing (
nil) , valid objects or objects that have been removed by SketchUp’s C++ side (ie “
This sounds like classic memory leak.
It can be caused by application bugs or often by device drivers.
IF there is any way on a Mac to update drivers for pointing devices, etc., (whatever is in use during SketchUp,) try to update them.
I’d suggest running test utilities to test your system RAM, HardDrives (and SolidState Drives if you have them.)
Are you working on a local file on your local drive ?
SketchUp does not do well working off virtual drives or network drives (DropBox, etc.)
Do you have SketchUp’s autosave feature switched ON ?
I’ve seen all sorts of issues with it, and it’s the first thing I switch off after installing a new version.
If you have a friend nearby with a Mac who has SketchUp installed, try it on their machine and see if the results differ.
Thanks for the explanation, Dan. I think I understand it better now.
OK, I installed an old copy of SU2015 and things ran without issue. Actually quicker by a bit: 1.59 seconds. So… Its either that memory handling thing with SU 2018 you mentioned Dan or my system. The code i must be OK.
I’ll let you know if I come up with anything else but thank you all for the dialog. This post has turned out to be more fun and interesting than fixing the problem itself!
You are sure that you have installed the latest maintenance release of SketchUp 2017 ?
It was a Mac only release numbered:
You might also try your script under a trial of SketchUp 2018 Pro.
@Barry, have you heard of a strange run away memory under SketchUp 2017 ?
Hmmm, … SU2017 uses OpenGL 3, and v15 still used OpenGL 2.something.
Do you have a 3D Connexxion Space Mouse? There have been some reports of their drivers causing memory leaks on the Mac.
… which is why I specifically mentioned device drivers and those for pointing devices in particular.
I have the latest Sketchup 2018 and the stock Apple mouse and all updated drivers and operating system.
You forum profile misled me …
Sorry… fixed that.
Ok so, assuming we dealing with a “memory hole”, whatever that is, is there anything I can do about it. I mean at the plugin level. Can I do anything to refresh or release memory resources before, during, or after the operation?
It is called “memory leak”, and it’s usually a bug. Often device drivers.
Make sure you wrap the geometric changes within an undo operation.
Never use UI.messagebox to create debug messages for code development. Instead write debug messages to the console using the global method
If possible try and do the unioning within a new group instance, rather than at the top level of the model, or within a geometric context that has a lot of other objects in it.
Did you try out Eneroth’s alternative boolean tools ? It would be a sort of test to see if the fault lies with the API’s native boolean tools.
I mentioned using test utilities to test your Hard Drive, SSD and DRAM to eliminate the possibility it comes from bad hardware in your machine. And testing on someone else’s machine that is close in configuration to yours.