Python plugin memory issues



  • On 24/04/2016 at 05:50, xxxxxxxx wrote:

    Hi All,
    Today I just made my first Python plugin!🙂 The plugin is a simple cloner based on the 'Objectdata' class. Its just cloning its children to the points of an object passed through PY_CLONER_LINK, a link box in the gui. Its main method, GetVirtualObjects, is displayed below.

    Now it works as expected, but when the link-object changes every frame (by a formula-deformer, for example), the frame rate of c4d steadily drops and in the activity monitor I can see memory use increasing. In fact, I made a little calculation and it seems that:

    memory increase per second = len(pts) x (frame_rate) x (memory_per_cloned_object)
    

    i.e. that new objects are being created every frame but none of the old objects are destructed. This can rapidly grow in the GB range.
    What is the cause of this memory increase, and can it be stopped? Or should I make another plugin like a particle modifier or something?

    To summarize: I want a plugin that updates the position of particles at every frame. The positions are calculated by another plugin, or an extension on this one. The number of particles is constant at runtime, but may change from session to session (for example at frame 0).

    I hope someone can help me out,
    regards,
    Hermen
    CINEMA 4D 17 Prime
    Mac OS X 10.10.5

    def GetVirtualObjects(self, op, hierarchyhelp) :

    bco = op.GetDataInstance()
            obj = bco.GetLink(c4d.PY_CLONER_LINK, doc=None, isinstanceof=c4d.Obase)
            instances = bco.GetBool(c4d.PY_INSTANCE_BOOL)
            
            clones = op.GetChildren()
            null = c4d.BaseObject(c4d.Onull)
            Nc = len(clones)
            if (not obj) or (not clones) : return null

    if obj.GetCache() :
                obj = obj.GetCache()
            elif obj.GetDeformCache() :
                obj = obj.GetDeformCache()
            elif obj.CheckType(c4d.Obase) :
                obj = self.MakeEditable(obj)

    pts = obj.GetAllPoints()        
            for i,p in enumerate(pts) :
                cln = c4d.BaseObject(c4d.Oinstance)
                bc = cln.GetDataInstance()
                k = i%Nc
                bc.SetLink(c4d.INSTANCEOBJECT_LINK, clones[k])
                bc.SetBool(c4d.INSTANCEOBJECT_RENDERINSTANCE, instances )
                cln.SetRelPos(p)
                cln.InsertUnder(null)
            
            return null



  • On 25/04/2016 at 09:30, xxxxxxxx wrote:

    Hi,

    first of all congrats to your first Python plugin! 🙂

    I was unfortunately not able to reproduce the issue you describe.
    But then again, I'm currently traveling and maybe didn't look closely enough.

    Actually there are two mechanisms, that should prevent a leak as you describe it. C4D takes care of getting rid of any previous/cached version, when you rebuild in GVO. And the Python garbage collections should take care of any orphaned objects (although I'm not completely sure, one could trick it in this situation).

    A few important parts of your code are also missing. For example what do you do in MakeEditable()? And do you use any kind of cache optimization?

    Can you perhaps also provide us with a scene, that makes your issue obvious (we'd replace your generator with the one I created from your source snippet)? A mail at sdks_support@maxon.net would do.
    And a few more details would be nice as well:
    Does it happen with any objects? Or only with primitives? Which path of the if "GetCache, elif GetDeformCache, elif MakeEditable()" is involved, when the issue occurs?

    Finally a few general thoughts:
    Most Generators in C4D work with a child hierarchy (e.g. Sweep NURB). So maybe the link field isn't actually needed, if you use the first child to clone on, instead?
    Then is your usage of GetCache() and GetDeformCache() not really sufficient. There's a code snippet in the documentation of GetCache(), showing how it's done correctly.
    And the final elif with CheckType() actually looks a bit weird to me in this situation. What is your intention there?



  • On 25/04/2016 at 13:17, xxxxxxxx wrote:

    Hi Andreas,
    Thanks for your reply, and happy traveling! Here are my answers to some of your questions:

    A few important parts of your code are also missing. For example what do you do in MakeEditable()? And do you use any kind of cache optimization?

    • MakeEditable, and the use of CheckType are a remnant of the past, before I knew of
        GetCache. I guess they're not needed anymore.
    • No cache optimization is used, because then the plugin doesn't follow the moving mother object.

    Can you perhaps also provide us with a scene, that makes your issue obvious (we'd replace your generator with the one I created from your source snippet)?

    • A mail with attachment is underway,  I'll try to stick in the plugin as well.

    ... Does it happen with any objects? Or only with primitives? Which path of the if "GetCache, elif GetDeformCache, elif MakeEditable()" is involved, when the issue occurs?

    • It happens with generators and deformed PolygonObjects, thus GetCache or GetDeformCache 
      are involved. With primitives the plugin doesn't work, as you explained I'm not using GetCache 
      the right way.

    Finally a few general thoughts:
    ... So maybe the link field isn't actually needed, if you use the first child to clone on, instead?
    -  I'd like to keep the link as to not to confuse the mother object with the clones which are iterated
      over, but I guess it could be done.
    Then is your usage of GetCache() and GetDeformCache() not really sufficient. There's a code snippet in the documentation of GetCache(), showing how it's done correctly.

    • This is probably why it won't work with primitives right now.

    And the final elif with CheckType() actually looks a bit weird to me in this situation.

    • As I said before, it's actually superfluous, so I have removed it.

    The issue remains, however, but curiously enough NOT IN DEBUG-MODE, so beware! I'm still curious to find out...

    Hope to hear from you soon, 
    best regards,
    Hermen


Log in to reply