Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Recent
    • Tags
    • Users
    • Admin
    • Login

    Python plugin memory issues

    Scheduled Pinned Locked Moved PYTHON Development
    3 Posts 0 Posters 358 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      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

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        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 [email protected] 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?

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          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

          1 Reply Last reply Reply Quote 0
          • First post
            Last post