Memory Leak in Brep.Trim()?

When I try to perform a high number of trimming operations in Python and Rhino.Common the memory usage of the Rhino processes goes right through the roof. After 100 trimming operations, memory has increased by approx. 1GB.

Below is the code, a Rhino model with a test surface is here: TrimLeakTest.zip(222.9 KB)

import rhinoscriptsyntax as rs
import scriptcontext
import Rhino
import random

def main():
    """ This test script takes an input surface, trims it with a number of 
    randomly placed boxes and puts the results back into the model as surfaces.
    
    After trimming 100 times the memory usage of Rhino has grown by approx. 1GB.
    """
    
    # USER INTEFACE ------------------------------------------------------------
    
    # get surface
    idSurface = rs.GetObject("select surface", 8)
    if idSurface == None: return
    # get number of trims to create
    nTrims = rs.GetInteger("number of trims", 100)
    if nTrims == None: return
    # get size of trimming boxes
    dSize = rs.GetReal("size of trim box", 1000)
    if dSize == None: return
    
    # PREPARATION --------------------------------------------------------------

    # get brep from guid and extract face and domains
    srfbrep = scriptcontext.doc.Objects.Find(idSurface).BrepGeometry
    face = srfbrep.Faces[0]
    domains = [face.Domain(i) for i in [0,1]]
    boxsize = Rhino.Geometry.Interval(-dSize/2, dSize/2)
    
    # EXECUTION ----------------------------------------------------------------

    # execute trims
    for i in range(nTrims):
        scriptcontext.escape_test()
        rs.Prompt("processing trim no. %d/%d" % (i+1, nTrims))
        # get random point on surface, plane in this point and a box
        p = face.PointAt(domains[0].ParameterAt(random.random()),
                         domains[1].ParameterAt(random.random()))
        plane = Rhino.Geometry.Plane(p, Rhino.Geometry.Vector3d(0,0,1))
        box = Rhino.Geometry.Box(plane, boxsize, boxsize, boxsize)
        # create box brep
        boxbrep = Rhino.Geometry.Brep.CreateFromBox(box)
        
        # TRIM input surface with box
        trimresult = srfbrep.Trim(boxbrep, rs.UnitAbsoluteTolerance())

        if trimresult != None and len(trimresult) > 0: 
            # create surface
            idTrim = scriptcontext.doc.Objects.AddBrep(trimresult[0], 
                                            Rhino.DocObjects.ObjectAttributes())
    
    # CLEAN UP -----------------------------------------------------------------
    
    
if __name__== "__main__":
    main()

I’ve already tried calling Dispose() for the intermediate results (boxbrep, trimresult) and even started the garbage collector manually with gc.collect(). It doesn’t help, the RAM usage linearly goes up from below 200MB to 99% of physical memory - which means I can trim some 500 boxes before I hit the 6 GB ceiling on my machine :frowning:

Does seem odd… At first I wondered if adding the objects to the document on every loop iteration (instead of adding them all at the end) was the problem, but no, not much difference there. I also thought that the trimmed sections might be unshrunk (with 10K control points each), but no, they are also shrunk at the moment they are trimmed… Also Undo does not reclaim any memory.

What’s also telling is that if I close the file and open a new one, the memory usage does not drop back to its “idle” level of around 200Mb either - it stays up where it was last left… so yes, perhaps a memory leak somewhere…

–Mitch

Thanks Mitch for having a look into this.

Interestingly Brep.CreateSolid() seems to work fine in a similar situation:

  • The base surface serves as the bottom of my solid
  • I am creating a ruled surface along a closed curve on the base surface (Ă  la ExtrudeNormal) to get the side surfaces
  • I offset the base surface to get the lid
  • then I send the three breps to CreateSolid() and get a perfectly closed volume with the top and bottom surface nicely trimmed and without memory issues (provided, I do call Dispose() on the input breps)

If nothing else helps, I am going to use this as a workaround - get the bottom face with DuplicateSubBrep() and throw away the rest :wink:

1 Like

I believe the low-level function that is doing the trimming is leaking. I’ll see that it is fixed for a future service release (hopefully SR7).

2 Likes