Sketchup 2016 performance issue with ruby coded material changes

I noticed a significant performance difference between sketchup 2015 and 2016 regarding material changes in ruby.
This code will perform way faster in 2015 than 2016

someGroup.entities.each { |elem|
elem.material = [0.0,1.0,0.0]
}

I wanted to report this as it makes my extension a lot less reactive in 2016. The only workaround i found so far was to embed this code into a

Sketchup.active_model.start_operation(“material update”, true)

Sketchup.active_model.commit_operation

But this causes other issues with the undo stack.
Anyone else experimenting the same issue ? Any other workarounds possible ?

Thanks

I ran into a similar problem when moving to 2016 because of a bug in settings for hardware acceleration. See this post:

Thanks for the post, i checked my settings and everything appears fine. My sketchup runs fine in general.

When profiling my extension it appears that only batch material updates are the issue.

Do you have some timing results to show the difference? And sample model?

Hi !

Sorry for late answer.
Yes i did run some tests, and with the exact same model and script, 2016 will perform approximately 6 times slower than sketchup 2015.

I use this simple function to test

def changeSelectionToRed()
	traceTime = Time.now
	sel = Sketchup.active_model.selection
	sel.each { |elem|
			elem.material = [1.0,0.0,0.0]
	}
	dt = Time.now - traceTime
	puts "material change in: " + dt.to_s
end

To test, you just need to select a bunch of faces and edges, and run the function. I did my test on a sphere with 200 faces. It will take 0.38s in 2015 and 2.14s in 2016.

Have you tried by wrapping your operations into start_operation where you disable the UI?

def changeSelectionToRed()
	traceTime = Time.now
        model = Sketchup.active_model
	sel = model.selection
	model.start_operation('Change Materials', true)
	sel.each { |elem|
			elem.material = [1.0,0.0,0.0]
	}
	model.commit_operation
	dt = Time.now - traceTime
	puts "material change in: " + dt.to_s
end

The second flag will disable the UI from updating between the start and commit. The only reason this isn’t true by default is for backwards compatibility. But in reality you should always do this - as otherwise SU will try to refresh everything you make a model change. It might very well be that the UI changes in SU2016 made refreshing the UI perform differently, but it might not be an issue if you make sure to disable it while you modify the model.

material change in: 0.193637 in v16 for me…

do you have any Material observers running in other plugins?

john

Yes i already tried that, it makes a difference, but i notice weird behaviour/crashes in my plugin when i start using those start_operation.

Finally i found out this is caused by the new ‘Default Tray’ in sketchup, it shows by default a lot of tabs that are probably refreshed everytime a script changes something. If i hide the tray, the performance is good again …

After a bit more digging, it turns out this is caused by the Statistics section inside the components tab, as soon as i remove it from the visible UI, everything is back to normal.
However, this very same tab does not cause the same issue in sketchup 2015 and earlier, it refreshes way faster.

This would be worth looking into. Wrapping model changes in start_operation is something one should always do when making bulk changes. It’s a big UX problem to not be able to undo an action in one step. The Extension Warehouse moderation will actually reject extensions because of this. Maybe start a new thread on this topic so we can follow up?

That’s an interesting observation. It could be that the new trays sends more update notifications to that module than what it previously did.

Thanks for your answer, i will look into that, i have a pretty complex ‘observer’ mechanism in place, and it does not play well with undos. I will continue experimenting.