Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Profiling Python Plugins

    Cinema 4D SDK
    r20 python
    5
    13
    1.7k
    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.
    • P
      pim
      last edited by

      Maxime pointed me to Profiling Python Plugins.

      However I have problems implementing it.
      I added all the code: import cProfile, def profile(func), def PluginMessage(msg_type, data) and in the Area class

          @profile
          def DrawMsg(self, x1, y1, x2, y2, msg):
      

      Now I get the console message:

          @profile
      NameError: name 'profile' is not defined
      
      M 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by ferdinand

        Hi,

        well have you exposed an implementation of the decorator profile like shown in the blog? Here is a small snippet to give you an idea how cProfile works in principal.

        Cheers,
        zipit

        import cProfile
        import math
        import pstats
        
        def some_function():
            """
            """
            profile = cProfile.Profile()
        
            # Start of profiling
            profile.enable()
            data = [math.sqrt(abs(math.sin(i * .001) * math.cos(i * .001)))
                    for i in range(100000)]
            profile.disable()
            # End of profiling
        
            stats = pstats.Stats(profile)
            stats.strip_dirs()
            stats.sort_stats("cumtime")
            stats.print_stats()
        
        if __name__ == "__main__":
            some_function()
        
        400002 function calls in 0.060 seconds
        
           Ordered by: cumulative time
        
           ncalls  tottime  percall  cumtime  percall filename:lineno(function)
           100000    0.018    0.000    0.018    0.000 {math.cos}
           100000    0.016    0.000    0.016    0.000 {math.sin}
           100000    0.016    0.000    0.016    0.000 {math.sqrt}
           100000    0.008    0.000    0.008    0.000 {abs}
                1    0.003    0.003    0.003    0.003 {range}
                1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        
        [Finished in 0.3s]
        

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • P
          pim
          last edited by

          @pim said in Profiling Python Plugins:

          @profile
          def DrawMsg(self, x1, y1, x2, y2, msg):
          

          I thought above should be enough.
          I guess I have to study the blog a bit better.
          Your example seems quite different and I will try it.

          Thanks, Pim

          1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand
            last edited by

            Hi,

            my example does nothing terribly unusual (I didn't red the whole blog though). I just gave you an example without the syntactic sugar of a decorator, because I assumed you are maybe a bit confused by it - do not know how decorators work - and therefor struggle to understand how cProfile works (which is not that hard to understand).

            Cheers,
            zipit

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 0
            • a_blockA
              a_block
              last edited by a_block

              While the output is not as detailed and neat as with zipit's use of profile, this is what I like to use to measure timing of functions:

              import time
              
              g_timingInfo = ['']
              def timing(f):
                  def wrapTiming(*args, **kwargs):
                      global g_timingInfo
                      time1 = time.clock()
                      ret = f(*args, **kwargs)
                      time2 = time.clock()
                      g_timingInfo.append('T %-8.2f ms : ' % ((time2-time1)*1000.0) + f.func_name)
                      return ret
                  return wrapTiming
              
              def PrintTiming():
                  global g_timingInfo
                  if len(g_timingInfo):
                      print '\nTIMING INFO:'
                      for t in g_timingInfo:
                          print t
                      print ' '
                  else:
                      print 'No timing info'
                  g_timingInfo = []
              

              In oder to use it, you simply decorate a function (or multiple) with @timing and at a later point of execution you call PrintTiming() to get the accumulated results printed to the Console.
              Like so:

              @timing
              def MyFunction():
                  pass
              @timing
              def MyFunction2():
                  pass
              
              def SomewhereInYourCode():
                  MyFunction()
                  for idx in xrange(100000):
                      MyFunction2()
                  PrintTiming()
              

              I like the decoration approach, as it's fast to pour some "probes" into your code without modifying the actual implementation of functions.
              Using module inspect you can easily beef it up by adding stack information or nice indentation of results based on call level.
              And this may also give you an idea, how to build decorations yourself. Useful for all kinds of stuff.

              Cheers

              M 1 Reply Last reply Reply Quote 0
              • M
                m_adam @pim
                last edited by

                @pim said in Profiling Python Plugins:

                Maxime pointed me to Profiling Python Plugins.

                    @profile
                NameError: name 'profile' is not defined
                

                I guess the issue is written clearly, the profile decorator is not defined. A decorator is nothing more than a function in Python, for more information see Primer on Python Decorators, so to fix your issue, you only have to copy the profile function provided in the Niklas blog post.

                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                1 Reply Last reply Reply Quote 0
                • M
                  mogh @a_block
                  last edited by mogh

                  @a_block

                  how would I implement your code in python 3.x (R23)
                  regarding

                  time.process_time() 
                  time.perf_counter() 
                  f.__name__
                  

                  this is also interesting: https://docs.python.org/3/library/timeit.html

                  I tried this but had no luck.

                  Got it somehow working but no timing to display ...

                  getting there still a little bit funky

                  TIMING INFO:
                  
                  T 0.00     ms : MyFunction
                  T 0.00     ms : MySecondFunction
                  T 15.62    ms : MySecondFunction
                  T 0.00     ms : MySecondFunction
                  T 15.62    ms : MySecondFunction
                  T 0.00     ms : MySecondFunction
                  T 15.62    ms : MySecondFunction
                  T 0.00     ms : MySecondFunction
                  T 0.00     ms : MySecondFunction
                  T 15.62    ms : MySecondFunction
                  T 0.00     ms : MySecondFunction
                  >>> 
                  
                  import c4d
                  import math
                  from c4d import gui
                  from c4d.documents import GetActiveDocument
                  import time
                  
                  g_timingInfo = ['']
                  def timing(f):
                      def wrapTiming(*args, **kwargs):
                          global g_timingInfo
                          time1 = time.process_time()
                          ret = f(*args, **kwargs)
                          time2 = time.process_time()
                          g_timingInfo.append('T %-8.2f ms : ' % ((time2-time1)*1000.0) + f.__name__)
                          return ret
                      return wrapTiming
                  
                  def PrintTiming():
                      global g_timingInfo
                      if len(g_timingInfo):
                          print ('\nTIMING INFO:')
                          for t in g_timingInfo:
                              print (t)
                          print (' ')
                      else:
                          print ('No timing info')
                      g_timingInfo = []
                  	
                  	
                  @timing
                  def MyFunction():
                      pass
                  @timing
                  def MySecondFunction():
                      data = [math.sqrt(abs(math.sin(i * .001) * math.cos(i * .001)))
                              for i in range(10000)]    
                      pass
                  
                  def SomewhereInYourCode():
                      MyFunction()
                      for idx in range(10):
                          MySecondFunction()
                      PrintTiming()	
                  
                  def main():
                      c4d.CallCommand(13957) # Konsole löschen  / delete console log
                  
                      SomewhereInYourCode()
                      c4d.EventAdd()
                  
                  if __name__=='__main__':
                      main()
                  

                  kind regards
                  mogh

                  1 Reply Last reply Reply Quote 0
                  • a_blockA
                    a_block
                    last edited by

                    how would I implement your code in python 3.x (R23)
                    

                    Not sure, what exactly your problem is. I'm currently using a simpler version of above code in C4D R23 and it works for me. Well, I build the string a bit differently and the print is also written differently in Python 3. But this doesn't seem to be your problem.
                    I'm aware there are parts of time module deprecated in Python 3, but... I mean, deprecated doesn't mean it's gone, only that it will be gone some time in future. And as I use it as a debugging tool, I don't care too much for the moment. The code is not meant to stay in my projects.

                    Can you post an error message maybe? I'm too lazy to test that exact version now.

                    M 1 Reply Last reply Reply Quote 0
                    • a_blockA
                      a_block @mogh
                      last edited by

                      @mogh It looks as if my reply this morning somehow got lost. I basically asked, what errors you get exactly?

                      M 1 Reply Last reply Reply Quote 0
                      • ferdinandF
                        ferdinand
                        last edited by

                        Hi Andreas,

                        no, your answer did not get lost, I just separated the threads, since this is basically a new question. Probably should have collected the two others posts too.

                        You will find the new thread here:

                        https://developers.maxon.net/forum/topic/12988/profiling-of-objects-in-python-3

                        Cheers,
                        Ferdinand

                        MAXON SDK Specialist
                        developers.maxon.net

                        1 Reply Last reply Reply Quote 0
                        • M
                          mogh @a_block
                          last edited by

                          @a_block your code says myfunction2 and mysecondfunction .. easy fix no problem then I was accidently moving block around thats why I crossed my questions out the last problem was just the python 3 thing ->
                          which I got working as far as getting some strange numbers with it (se top post )

                          I have a feeling I upset you that was not my intend and I am sorry, If so please acept my appologie.
                          kind regards
                          mogh

                          1 Reply Last reply Reply Quote 0
                          • a_blockA
                            a_block
                            last edited by

                            Good catch, I fixed the post.

                            No, you didn't upset me. And I may have been a bit short, asking for actual errors.
                            For me the latter indeed is an important point. You will help yourself a lot, improving the information contained in a question. For example when talking about errors, but not providing any information or details about the actual errors. On your journey into C4D development and Python programming the Console is your friend and more often than not it already contains good information to solve an issue (and even if messages therein seem to make no sense, they may mean something to others). If I have been too harsh, I apologize, but also please try to view it from the other side. The people wanting to help, spend time for this. Having to ask the same questions again and again, just to find out what the actual question or problem is, is just time lost. For the one wanting to help simply lost and for the one asking it only takes longer to get the desired answer. On top assume, there may be multiple people wanting to help, so parts of this equation even multiply... so asking good questions, will help you reaching a solution in shorter amount of time and save time on side of those helping, which in turn will increase chances to get help at all.

                            I hope, you don't get me wrong. Really in this case it wasn't a big deal and it was probably my fault, to just insist on an error message without further words. Sorry for that. And the above, while addressing you, you should actually rather read as a hint to everybody asking questions on any forum.
                            In a nutshell, if you are having a problem, try to help other people help you.

                            And please keep asking questions. It's the best way to improve as a developer. Believe me, I know, what I am talking about. Looking at my code should be evidence enough, I asked way too few questions...

                            Cheers

                            1 Reply Last reply Reply Quote 0
                            • ferdinandF
                              ferdinand
                              last edited by

                              Hi,

                              without further feedback, we will consider this thread as solved by tomorrow and flag it accordingly.

                              Cheers,
                              Ferdinand

                              MAXON SDK Specialist
                              developers.maxon.net

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