Performance Issue when supressing many features in part document

Performance Issue when supressing many features in part document

thomas_wegerBYFE5
Contributor Contributor
9,205 Views
14 Replies
Message 1 of 15

Performance Issue when supressing many features in part document

thomas_wegerBYFE5
Contributor
Contributor

Hello,

I am experiencing some performance issues when working with a "lot" of feature supressing in a part document.

What I do is geting the parameters from a SQLite Database. I store the in user parameters. Depending on the values from the database I supress and activate different features of the part.
However doing this takes about about 20 seconds or so.
I already deactivated the screen update. My PC has 16 GB RAM and an i7 processor with a medium grafic card. Not the best but not the worst so to say.
Is there an option in iLogic to increase the speed when using Feature.IsAcitve? or is there a completelty different approach in order to takle such kind of part?
Attache a picture from the code. I could attach the whole code but basically it is a lot of feature supressing.

 

0 Likes
Accepted solutions (1)
9,206 Views
14 Replies
Replies (14)
Message 2 of 15

JelteDeJong
Mentor
Mentor

In some cases, it helps to use a transaction. You could do something like this:

 

Dim doc As PartDocument = ThisApplication.ActiveDocument
Dim features = doc.ComponentDefinition.Features

Dim featuresToSuppress As New List(Of String)
featuresToSuppress.Add("Add")
featuresToSuppress.Add("your")
featuresToSuppress.Add("features")
featuresToSuppress.Add("here")


Dim trans = ThisApplication.TransactionManager.StartTransaction(doc, "Suppress features")

Try
    For Each featureName As String In featuresToSuppress

        features.Item(featureName).Suppressed = True

    Next
Catch ex As Exception
    MsgBox(ex.Message)
Finally
    trans.End()
End Try

 

Also, have a look at this post:

https://modthemachine.typepad.com/my_weblog/2015/09/improving-your-programs-performance.html

Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Blog: hjalte.nl - github.com

Message 3 of 15

JMGunnar
Collaborator
Collaborator

2 options 

1 options 

you can try too use function 

SetEndOfPartToTopOrBottom

then  run rule 

 

 

Value = MoveEndOff

Dim oDoc As PartDocument = ThisDoc.Document

If MoveEndOff

    oDoc.ComponentDefinition.SetEndOfPartToTopOrBottom(False)

Else

   Feature.InventorFeature(“Extrusion1”).SetEndOfPart(False)

End If

 

Best Regards Johan

 

Also, have a look at this post:

@PaulMunford  Reliable-Modeling-Techniques-Complex-Part-Design-Inventor

https://www.autodesk.com/autodesk-university/class/Reliable-Modeling-Techniques-Complex-Part-Design-...

0 Likes
Message 4 of 15

WCrihfield
Mentor
Mentor
Accepted solution

I'm not sure what may be required to speed up the data collecting part from the SQLite database, but generally speaking, the fewer read and/or write calls between the two, the better.  For example it is faster to copy (or paste) an entire 2-directional array of data from (or to) an Excel spreadsheet at once than it is to extract (or write) the data from (or to) each cell individually in a loop.  Once you have the data held in memory (assigned to a Variable), then you can work with that data faster, with less processing.

 

Also, just to add to Jelte's idea in the earlier post...if you were to get all the features you want to control into one or two ObjectCollections (not a List), then you could suppress or un-suppress them all at once, instead of in a loop, using the built-in methods just for that purpose (PartComponentDefinition.SuppressFeatures()PartComponentDefinition.UnsuppressFeatures()).  That should help out some with the processing speed.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 15

thomas_wegerBYFE5
Contributor
Contributor
@JelteDeJong , @ johan.gunnar, @WCrihfield thank you very much for the inputs 🙂 I will try them and give you feedback.
0 Likes
Message 6 of 15

thomas_wegerBYFE5
Contributor
Contributor

@WCrihfield: thank you very much for your input. I actually have no issues with the speed of reading the SQLite database (its also true I just do it once in order to get the parameters).  It was more to give context. But still thank you very much for your input.

I think storing the features in the ObjectCollection is very fast. And your suggestion to use the PartComponentDefinition.SuppressFeatures() would work great. However I implemented it and it seems to me that if I use SuppressFeatures() in an ObjectCollection where the feature is already supressed it gives an error.  Working with Feature.isActive or features.Item(featureName).Supressed = True (like suggested from @JelteDeJong ) does accept if the state is already. Maybe I am wrong... and there are dependencys between the features (its not my model, I am just trying to optimize it)

StyleSelector.Add(myPartFeatures.Item("my"))
StyleSelector.Add(myPartFeatures.Item("features"))
StyleSelector.Add(myPartFeatures.Item("another one"))

'This works
Feature.IsActive("my") =True
Feature.IsActive("features") =True
Feature.IsActive("another one") =True
oPartCompDef.SuppressFeatures(StyleSelector)

'This alone not
oPartCompDef.SuppressFeatures(StyleSelector)

 

0 Likes
Message 7 of 15

thomas_wegerBYFE5
Contributor
Contributor

I kina combined the two ansswers as I always got an error when there was a part which was supressed in a list which I wanted to supress (so all the others would be not suppressed)...see my post above

Sub featuresToSuppressSub(ByRef featuresToSuppressList As List(Of String), suppress As Boolean, loggerMsg As String)
	Dim doc As PartDocument = ThisApplication.ActiveDocument
	Dim Features = doc.ComponentDefinition.Features

	Try
		bulkfeaturesToSuppressSub(featuresToSuppressList, supress)
		Logger.Debug("BulkSupressSuccess: " & loggerMsg)
	Catch
		Dim trans = ThisApplication.TransactionManager.StartTransaction(doc, "Suppress features")
		Try
			For Each featureName As String In featuresToSuppressList
				Features.Item(featureName).Suppressed = True
			Next
			Logger.Debug("Jetzt hab ich einzeln gemacht: " & loggerMsg)
		Catch ex As Exception
			MsgBox(ex.Message)
		Finally
			trans.End()
		End Try
	End Try


End Sub


Sub bulkfeaturesToSuppressSub(ByRef AfeaturesToSuppress As List(Of String), suppress As Boolean)
	' Find all selected occurrences and add them to an ObjectCollection.
	Dim AStyleSelector As ObjectCollection
	AStyleSelector = ThisApplication.TransientObjects.CreateObjectCollection
	Dim oDoc As PartDocument = ThisApplication.ActiveDocument
	Dim oPartCompDef As PartComponentDefinition

	oPartCompDef = oDoc.ComponentDefinition
	
	Dim myPartFeatures As PartFeatures
	myPartFeatures = oPartCompDef.Features


	Dim i As Integer
	i = AfeaturesToSuppress.Count
	Dim xObject(i) As PartFeature
	i = 0
	For Each featureName As String In AfeaturesToSuppress
		xObject(i) = myPartFeatures.Item(featureName)
		supressCheck(xObject(i), suppress)
		AStyleSelector.Add(xObject(i))
		i = i + 1
	Next

	If suppress = True Then
		oPartCompDef.SuppressFeatures(AStyleSelector)
	Else
		oPartCompDef.UnsuppressFeatures(AStyleSelector)
	End If
End Sub


Sub supressCheck(partfeature As PartFeature, supress As Boolean)
	If partfeature.Suppressed = supress
		Logger.Debug(partfeature.Name & "was equal ")
		'partfeature.Suppressed = Not supress
	End If
End Sub

 

0 Likes
Message 8 of 15

WCrihfield
Mentor
Mentor

Hi @thomas_wegerBYFE5.  Did that last code you posted increase the performance noticeably, as you were hoping for?  It seemed to me like it might still benefit from a little tweaking to condense & simplify it a bit, so I created an alternate version of it for you to review.  This version is just one Sub routine, instead of three, and only attempts to change the suppression status of any feature, if that feature does not already match the status being called for.  That testing is done before they get put into the ObjectCollection, that way the 'group' process should work OK for you.

It first makes sure that the 'active' document is actually a part, to avoid that potential problem.  Then makes sure each named feature can be found, then checks suppression status.  If it was found, and suppression status does not match requested status, it gets added to the collection.  Then the appropriate method is used to match the requested suppression status.  Then I just added a couple lines at the end for updating & saving the part, but only if needed, and left the 'save' line commented out for now.

 

Sub SetFeaturesSuppression(FeatureNames As List(Of String), bSuppress As Boolean)
	If IsNothing(FeatureNames) OrElse FeatureNames.Count = 0 Then Exit Sub
	If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kPartDocumentObject Then Exit Sub
	Dim oPDoc As PartDocument = ThisApplication.ActiveDocument
	Dim oPDef As PartComponentDefinition = oPDoc.ComponentDefinition
	Dim oFeatures As PartFeatures = oPDef.Features
	Dim oFeatsToProcess As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
	For Each oName In FeatureNames
		Dim oFeat As PartFeature = Nothing
		Try : oFeat = oFeatures.Item(oName) : Catch : Continue For : End Try
		If IsNothing(oFeat) Then Continue For
		If oFeat.Suppressed <> bSuppress Then oFeatsToProcess.Add(oFeat)
	Next
	If bSuppress = True Then
		oPDef.SuppressFeatures(oFeatsToProcess)
	Else
		oPDef.UnsuppressFeatures(oFeatsToProcess)
	End If
	If oPDoc.RequiresUpdate Then oPDoc.Update2(True)
	'If oPDoc.Dirty Then oPDoc.Save
End Sub

 

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 9 of 15

thomas_wegerBYFE5
Contributor
Contributor

@WCrihfield: indeed, you approach to just add those in the list who are different is much cleaner then mine to check if it fails and then do it one by one. You have been a great help to sort out this problem. Thank you very much!
Greetings from south tyrol, Italy when you are arround I pay you a coffee!

0 Likes
Message 10 of 15

thomas_wegerBYFE5
Contributor
Contributor

@WCrihfieldsorry to bother you again. Does this could actually also work for AssemblyDocuments?
I found AssemblyComponentDefinition.SupressFeatures in the documentation but I am not sure...if those features are specific features within the parts in the assembly?
I want to do the same with the list but with parts in an assembly.
I tried to modify your code...

So far we do it like this:

 

 Case 30
    N = 31
    For I = 1 To N
       Component.IsActive(Name_5 & I) = True
    Next I	
End Select

 

 

But its also slow...I thought its because we work with constraints and not placing the components with coordinates...but maybe its similar to the feature suppression?

 

TestCode for the Assembly

 

 

Sub featuresToSuppressSub(FeatureNames As List(Of String), bSuppress As Boolean, loggMsg As String)
	If IsNothing(FeatureNames) OrElse FeatureNames.Count = 0 Then Exit Sub
	'If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kPartDocumentObject Then Exit Sub
	Dim oPDoc As AssemblyDocument = ThisApplication.ActiveDocument
	'Dim oPDoc As PartDocument = ThisApplication.ActiveDocument
	
	Dim oPDef As AssemblyComponentDefinition = oPDoc.ComponentDefinition
	'Dim oPDef As PartComponentDefinition = oPDoc.ComponentDefinition
	
	Dim oFeatures As Features = oPDef.Features
	Dim oFeatsToProcess As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
	For Each oName In FeatureNames
		Dim oFeat As PartFeature = Nothing
		Try : oFeat = oFeatures.Item(oName) : Catch : Continue For : End Try
		If IsNothing(oFeat) Then Continue For
		If oFeat.Suppressed <> bSuppress Then oFeatsToProcess.Add(oFeat)
	Next
	If bSuppress = True Then
		oPDef.SuppressFeatures(oFeatsToProcess)
	Else
		oPDef.UnsuppressFeatures(oFeatsToProcess)
	End If
	If oPDoc.RequiresUpdate Then oPDoc.Update2(True)
	'If oPDoc.Dirty Then oPDoc.Save
End Sub

 

0 Likes
Message 11 of 15

WCrihfield
Mentor
Mentor

Hi @thomas_wegerBYFE5.  If any of those named features were created directly in the context of the main (top level) assembly, and not while editing components, then that code would likely work OK.  But if none of those features were created directly in the top level assembly, but only in the parts within the assembly, then one major change would be needed.  For your code to work on the parts within the assembly, I would suggest that you get the AssemblyDocument.ReferencedDocuments (top level referenced documents only), or AssemblyDocument.AllReferencedDocuments (all levels of referenced documents in assembly structure) to a variable (DocumentsEnumerator Type).  Then create a loop of those referenced documents.  Then, just inside that loop, use 'If oRefDoc.IsModifiable = False Then Continue For', and then filter for parts only using 'If oRefDoc.DocumentType <> DocumentTypeEnum.kPartDocumentObject Then Continue For'.  Then either copy your code for processing parts into that loop below that point, or just call your Sub routine to run that will process the part.

 

Edit:  If you plan on calling your Sub routine (for processing parts) within that loop of referenced documents, you may need to modify your Sub routine's definition line to include the 'input' PartDocument object for it to process, then get rid of the use of 'ThisApplication.ActiveDocument' within the routine to set the document variable's value.  That would give it much better control of the situation.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 12 of 15

thomas_wegerBYFE5
Contributor
Contributor

Hi! Thank you for your kind message. I think I was not precise in my message. What I wanted to do was to store all parts off an assembly in a list or so and supress the complete list at once. Similar what you showed me with the features in the parts. As doing a loop over all parts (or a specific number od parts) in an assembly (component.active) is very slow. I kinda hoped maybe there is a similar command for parts in an assembly. As far as I understood your message you understood I want to loop over all parts and inside the part loop over the features...
I tried to do this: supress folder but the performance does not change much... (we speak about a copule of seconds 5-10 or so...)

0 Likes
Message 13 of 15

WCrihfield
Mentor
Mentor

Hi @thomas_wegerBYFE5.  I do not know of a built-in API or iLogic method for suppressing a group of assembly components at once.  The only alternative I can think of, other than the folder suppression technique you mentioned, to simulate selecting a group of components in the browser tree, then right-click, and choose Suppress.  The internal name of the ControlDefinition (command) that gets executed when you do that is called "AssemblyCompSuppressionCtxCmd".  To simulate that action, you would use the Document.SelectSet.SelectMultiple method to put them all into the SelectSet, then get that ControlDefinition object and use its Execute method.  I generally do not like executing commands from code if there is any other way of doing the same thing, but I will leave that decision up to you to experiment with.  I do not know if that process would be any faster to process.

 

Edit:  Upon further inspection, that command 'toggles' suppression status, not just suppresses them.  So the components would need to be sorted or filtered before/filtered before adding them to the SelectSet, to avoid problems.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 14 of 15

thomas_wegerBYFE5
Contributor
Contributor

@WCrihfield(short update for your info) the following code works similar to supressing folders. Unlike the solution with suppresing the folders (suppress-folder-in-assembly ) it has not the drawback that you need to specifiy the name of the BrowserPane Set (oPane = oDoc.BrowserPanes("Model")) which is a bit dangerous as in a German Inventor this is called "Modell" and maybe in another Inventor language again different. Currently we are checking if this code works also for the Autodesk Platform Service (as you dont have a GUI there...). So far the perfomance is much better. From around 1 minute for suppressing to 10 seconds.

 

Dim doc As AssemblyDocument
doc = ThisDoc.Document

Logger.Debug("Assembly has: " & doc.ComponentDefinition.Occurrences.Count & " components.")
Dim stopwatch  As New Stopwatch()
stopwatch.Start()

Dim objCol As ObjectCollection
objCol = ThisApplication.TransientObjects.CreateObjectCollection

Dim occ As ComponentOccurrence
For Each occ In doc.ComponentDefinition.Occurrences
	If occ.Suppressed=False Then
	objCol.Add(occ)
	End If
Next

Dim selSet As SelectSet
selSet = ThisDoc.Document.SelectSet
selSet.SelectMultiple(objCol)

ThisApplication.CommandManager.ControlDefinitions("AssemblyCompSuppressionCtxCmd").Execute2(True)

stopwatch.Stop()

Logger.Debug("Elapsed time: " & stopwatch.Elapsed.TotalSeconds & " seconds.")

 

0 Likes
Message 15 of 15

thomas_wegerBYFE5
Contributor
Contributor

Update, while the code above works fine on the Inventor with GUI it does not when you use Inventor on a server without GUI.
This code reaches similar performance by using the transaction manager:

https://help.autodesk.com/view/INVNTOR/2024/ENU/?guid=GUID-991ABB26-6113-4E27-83F8-1699F259772E

 

Dim trx = ThisServer.TransactionManager.StartTransaction(doc, "Suppress All")
Try
	Dim occ As ComponentOccurrence
	For Each occ In doc.ComponentDefinition.Occurrences
		occ.Suppress
	Next
Catch
	' An error occurred. Abort the transaction:
	trx.Abort()
	Throw ' this will exit the rule
End Try
trx.End()

 

0 Likes