Dynamo crash: Python node extracting plane from directshape

I am using DirectShape faces as reference planes for placing face based families. This process essentially allows families to be oriented (rotated in all three axis) which is very useful. I have decided to start refactoring key parts of my working scripts onto python nodes, in the hope that they will be more compact and robust, and reusable. Maybe even faster? :persevere:

This is where the problems arise…

I have two functions I wish to perform:

  1. Directshape.ByPlane
  2. Plane.ByDirectshape

I have attached demo scripts for both using nodes and designscript.

The screengrab below shows my approach to step two, both in nodes, and python. The python function works fine with less than about 100 input directshapes. when i increase the number, dynamo either hangs or revit crashes. :cry: target is about three thousand planes. I have tried calling Dispose() on non-returned geometry, but that doesn’t seem to affect the performance.

Have i missed something important? is my function inefficient?

In order to recreate the issue you will need to run step 1 Directshape.ByPlane.dyn first to create the directshapes (note: they are small!)

Thanks in advance for any advice :heart_eyes:

ByDirectShape

Directshape.ByPlane.dyn (13.5 KB)
Plane.ByDirectshape.dyn (14.7 KB)

read this:

sorry, just saw you tried disposal already - when your crash occurs, what exactly happens? Does it hang? What does memory usage look like then - does memory keep increasing or stay constant?

also disposal it not really going to improve performance, but it would hopefully stop dynamo from hanging - when you get a crash at - are you running out of memory or have a bunch free?

have you tried running just your python code, but not running the DS function on the resulting planes?

Hi Michael thanks memory usage stays constant. I have about 25GB spare memory, and Revit is using less than 1GB when dynamo stops responding. CPU stays at about 20%. Yeah i can’t see disposal being an issue here.

This behavior is exactly an indication that disposal is the issue - when dynamo geometry types are garbage collected via the CLR garbage collector this results in undefined behavior and hangs. There may be some other geometry you are not disposing. (this is one potential).

I’m curious if you find that everything works if you only run the python but not the DS code block.

what is the return type of your call e.Geometry() - it does not look like you disposed this? Is this a dynamo geometry type?

I guess that is a geometry conversion - like Element.Geometry - definitely call dispose on each of those geometries in geo.

Element.Geometry() returns a list of dynamo geometry. I didn’t realise this was creating new geometry. i assumed this was only accessing existing objects

Geometry

This still causes instability

usually the geometry library and dynamo libraries in general are immutable when possible and each conversion returns new geometry - your test above is a good one though and I’m confused by it - seems like a possible bug in the conversion code itself leaking for directShapes. (not disposing)

Could you try disposing those return objects manually before returning (lets say just a number or something) and see what happens?

Would you be able to post that tiny sample code above which illustrates the crash to the dynamoRevit GitHub as an issue.

just another thought - do all the geometry conversions succeed? If some of them fail I could see the converter code not disposing correctly. (still would be a bug on the DynamoRevit side)

Ok i’ve tried disposing of each piece of geometry individually here:
disposalTest

Seems to be OK

disposalTest-result

1 Like

staring at the revit solid to dynamo solid code I am finding this, which looks like a curve which is never disposed… https://github.com/DynamoDS/DynamoRevit/blob/112f8aac1e34cb10df94076ee956f8dd43d17ae5/src/Libraries/RevitNodes/GeometryConversion/DynamoToRevitBRep.cs#L113

edited because that converter was in the wrong direction I think.

so what happens with 10,000? :slight_smile:

1 Like

My directshapes are rectangular faces 100mm x 100mm. So each has one planar face and four linear edges. My initial post has the file that creates them.

:+1:
It takes about 50 seconds which is absolutely fine. Thanks for your help. I’m pretty sure this has solved my problem. It seems i wasn’t taking dispose seriously enough. I mistakenly assumed that only geometry i was explicitly creating needed disposing, however Element.Geometry() is actually creating geometry. Is that correct?

disposalTest-10000

If there is an easier way to ensure i am disposing of everything correctly i’d love to hear ideas! Is there a way in python of wrapping geometric functions in a Dispose block? something like the C# using statement? Maybe python ‘with’?

1 Like

yes, element.Geometry() is creating new dynamo geometry each time it’s invoked.

I wish the Dynamo team had time to take on a project for alerting user devs to the geometry creation code which is not disposed in their python and c# nodes. As it stands I do not think we have the bandwidth… it would be a very interesting use case for a reflection based extension to dynamo… @Keith_Alfaro

1 Like

Here is the Plane.ByDirectShape solution with geometry disposal. No crash for 18,156 elements. @Michael_Kirschner2 i’m pretty happy with this, especially since i was having issues only a couple previously!

This will hopefully become a method in a class i’m working on for sorting, checking and placing a range of families on planes.

1 Like

If this was done with OOTB nodes, can geometries be disposed?
How does it works?
Can it just be done in a Python node?