Author Topic: (vlax-release-object obj) vs (setq obj nil)  (Read 17363 times)

0 Members and 2 Guests are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
(vlax-release-object obj) vs (setq obj nil)
« Reply #15 on: August 03, 2004, 03:20:31 AM »
sinc ;

The comments from your post are essentially my understanding of the situation.

I have dragged out some old test code which may demonstrate that the memory usage after creating 1,000,000 unreleased global references is considerably different to creating 1,000,000 unreleased local references.
If local unreleased {by user code } references were retained and not automatically released the memory usage for test 101 and 103 would be similar.

I understand that this test is not the most scientific ever produced , but the results are sufficient for me to form an opinion.

I will continue to declare Autocad based objects as locals and not release or nil them. Objects created from any external ActiveX Server will be released and nilled as I am currently doing.

This is not intended as a pissing contest.
Perhaps someone has test results that can better define any differences. I would be interested in seeing them, particularly if the results show me how to improve my code.
Regards.Kerry
Code: [Select]

(vl-load-com)
(defun c:test101 (/ oLine StartPoint EndPoint cnt)
   (gc)
   (or gx:acadapp (setq gx:acadapp (vlax-get-acad-object)))
   (or gx:activedoc (setq gx:activedoc (vla-get-activedocument gx:acadapp)))
   (or gx:modelspace (setq gx:modelspace (vla-get-modelspace gx:activedoc)))
   ;;
   ;;
   (setq StartPoint '(0 0 0)
         EndPoint   '(100 100 100)
         cnt        0
   )
   (vla-put-color (setq oLine (vla-addline gx:modelspace
                                           (vlax-3d-point StartPoint)
                                           (vlax-3d-point EndPoint)
                              )
                  )
                  cnt
   )
   (vl-cmdf "status")
   (mem)
   (prompt "\n Be prepared to wait a while ...... ")
   (repeat 500000 (setq cnt (1+ cnt)) (test101 (rem cnt 255)))          
   (vl-cmdf "status")
   (mem)
   (princ)
)
(defun test101 (newcolor / oLine tmp)
   (vla-put-color (setq oLine (vlax-ename->vla-object (entlast))) newcolor)
   (setq tmp (vla-get-layers gx:activedoc))
   (princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:test102 (/ oLine StartPoint EndPoint cnt)
   (gc)
   (or gx:acadapp (setq gx:acadapp (vlax-get-acad-object)))
   (or gx:activedoc (setq gx:activedoc (vla-get-activedocument gx:acadapp)))
   (or gx:modelspace (setq gx:modelspace (vla-get-modelspace gx:activedoc)))
   ;;
   ;;
   (setq StartPoint '(0 0 0)
         EndPoint   '(100 100 100)
         cnt        0
   )
   (vla-put-color (setq oLine (vla-addline gx:modelspace
                                           (vlax-3d-point StartPoint)
                                           (vlax-3d-point EndPoint)
                              )
                  )
                  cnt
   )
   (vl-cmdf "status")
   (mem)
   (prompt "\n Be prepared to wait a while ...... ")
   (repeat 500000 (setq cnt (1+ cnt)) (test102 (rem cnt 255)))          
   (vl-cmdf "status")
   (mem)
   (princ)
)
(defun test102 (newcolor / oLine tmp)
   (vla-put-color (setq oLine (vlax-ename->vla-object (entlast))) newcolor)
   (setq tmp (vla-get-layers gx:activedoc))
   (vlax-release-object oLine)
   (vlax-release-object tmp)
   (princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:test103 (/ oLine StartPoint EndPoint cnt)
   (gc)
   (or gx:acadapp (setq gx:acadapp (vlax-get-acad-object)))
   (or gx:activedoc (setq gx:activedoc (vla-get-activedocument gx:acadapp)))
   (or gx:modelspace (setq gx:modelspace (vla-get-modelspace gx:activedoc)))
   ;;
   ;;
   (setq StartPoint '(0 0 0)
         EndPoint   '(100 100 100)
         cnt        0
   )
   (vla-put-color (setq oLine (vla-addline gx:modelspace
                                           (vlax-3d-point StartPoint)
                                           (vlax-3d-point EndPoint)
                              )
                  )
                  cnt
   )
   (vl-cmdf "status")
   (mem)
   (prompt "\n Be prepared to wait a while ...... ")
   (repeat 500000 (setq cnt (1+ cnt)) (test103 cnt))
   (vl-cmdf "status")
   (mem)
   (princ)
)


(defun test103 (cnt /)
   (vla-put-color (set (read (strcat "oLine-" (itoa cnt))) (vlax-ename->vla-object (entlast)))
                  (rem cnt 255)
   )
   (set (read (strcat "oLayerCollection-" (itoa cnt)))
        (vla-get-layers gx:activedoc)
   )
   (princ)
)
(princ)


The test results : be prepared to wait .. restart Autocad between tests ..
Code: [Select]

Command: (load "memtest")
Command: test101
status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1321.5 MBytes
Free temp disk (D:) space: 1321.5 MBytes
Free physical memory: 238.8 Mbytes (out of 511.5M).
Free swap file space: 3275.9 Mbytes (out of 3551.9M).

Command: ; GC calls: 23; GC run time: 373 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   321     9     7    22  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 69, free: 3

 Be prepared to wait a while ......
 status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1305.7 MBytes
Free temp disk (D:) space: 1305.7 MBytes
Free physical memory: 181.3 Mbytes (out of 511.5M).
Free swap file space: 3219.3 Mbytes (out of 3551.9M).

Command: ; GC calls: 493; GC run time: 15443 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   338     7     5    23  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 70, free: 2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Command: (load "memtest")

Command: test102
status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1306.0 MBytes
Free temp disk (D:) space: 1306.0 MBytes
Free physical memory: 240.7 Mbytes (out of 511.5M).
Free swap file space: 3281.3 Mbytes (out of 3551.9M).

Command: ; GC calls: 23; GC run time: 343 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   321     9     7    22  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 69, free: 3

 Be prepared to wait a while ......
 status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1290.2 MBytes
Free temp disk (D:) space: 1290.2 MBytes
Free physical memory: 183.3 Mbytes (out of 511.5M).
Free swap file space: 3225.1 Mbytes (out of 3551.9M).

Command: ; GC calls: 493; GC run time: 15570 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   338     7     5    23  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 70, free: 2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Command: (load "memtest")

Command: test103
status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1290.4 MBytes
Free temp disk (D:) space: 1290.4 MBytes
Free physical memory: 239.2 Mbytes (out of 511.5M).
Free swap file space: 3281.0 Mbytes (out of 3551.9M).

Command: ; GC calls: 23; GC run time: 344 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2396   618   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   321     9     7    22  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 69, free: 3

 Be prepared to wait a while ......
 status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1274.7 MBytes
Free temp disk (D:) space: 1274.7 MBytes
Free physical memory: 55.2 Mbytes (out of 511.5M).
Free swap file space: 3070.9 Mbytes (out of 3551.9M).


Command: ; GC calls: 124; GC run time: 57013 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2396   618   104    10  bytecode area
4096  5894     1     1   393  CONS memory
  32   850  1133  1087     1  ::new
4096  6932    13    13   463  DM Str
4096 21777   411     8  1479  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 2350, free: 0
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

daron

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« Reply #16 on: August 03, 2004, 08:53:06 AM »
Sorry Kerry, I can't show anything or help improve your code. All I can do is share what I can recollect of an experience I had in not releasing my objects. When I learned ActiveX, not too long ago, I was taught to always release my objects. As I progressed and found myself writing more code using AX, I became lazy, too busy or both. I developed a routine that would take a selected group of objects, move them near the 0,0 area and wblock them out according to the number of a piece of text within the selection. This would repeat as often times as there were objects with this type of text in the selection. There were a few more steps to the function, like adding a title-block with all possible information and printing the area out. At first, I left out the releasing portion of the code. It worked for a short time. In a project where I had 100 groups of objects to process, I found the memory of my computer quickly eaten up. 100 property lots (groups of objects) was small scale, so I knew I needed to do something. I got over my laziness, set up the necessary vlax-release-objects and began again on a fresh day. The start of the job didn't increase nor decrease in speed, but I was able to finish the job and each one after, without the type of slow down I had experienced previously.

Don't do it anymore. Can't test it anymore, but I would concur with se7en, release your objects. It certainly doesn't hurt. At the same time, I believe there are some procedures out there that have been written that you can download to not have to write it out each time, but just use them.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
(vlax-release-object obj) vs (setq obj nil)
« Reply #17 on: August 03, 2004, 09:36:24 AM »
Daron ,
Were these global variables holding the objects or local ?

I would have to see the code to pass comment.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

SMadsen

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« Reply #18 on: August 03, 2004, 12:30:34 PM »
What bugs me most about the missing documentation is that I have no idea if unreleased objects causes bad things such as memory leaks and slowed performance. It's very common to nest calls through multiple objects without a chance of decrementing the reference count.

Does a call like (vla-get-name (vla-item (vla-get-documents (vlax-get-acad-object)) myIndex)) sound familiar? It increments the reference count of both the Documents collection and the application object but there's no chance to release the references. Try this little test:

Command: (vlax-release-object (vlax-get-acad-object))
3

Command: (vlax-release-object (vla-get-documents (vlax-get-acad-object)))
1

Command: (vla-get-name (vla-item (vla-get-documents (vlax-get-acad-object)) 0))
"Drawing2.dwg"

Command: (vlax-release-object (vla-get-documents (vlax-get-acad-object)))
2

Command: (vlax-release-object (vlax-get-acad-object))
7

Repetition of the last two calls will never return smaller counters than the above, which means that there are references that can not be released.

Now, the document collection and the application will always be referenced so it doesn't matter that they can't be cleaned up but if you go further down the hierarchy than you may lock objects that otherwise were up for garbage collection (and global/local referencing is indifferent to this).
As mentioned previously, with in-process objects it may not be a problem at all but just to know that there may be a problem and that it's not documented .. well, that sucks.

daron

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« Reply #19 on: August 03, 2004, 01:15:15 PM »
I believe they were local, Kerry.

sinc

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« Reply #20 on: August 05, 2004, 04:21:01 PM »
Quote from: SMadsen
Now, the document collection and the application will always be referenced so it doesn't matter that they can't be cleaned up but if you go further down the hierarchy than you may lock objects that otherwise were up for garbage collection (and global/local referencing is indifferent to this).
As mentioned previously, with in-process objects it may not be a problem at all but just to know that there may be a problem and that it's not documented .. well, that sucks.

I have confirmed that there is a definite bug in here.  Normal objects seem fine, but distributed objects (ActiveX) are definitely buggy.

At this point, I'm not familiar enough with ActiveX to be sure if the problem is an ActiveX problem, or a problem in Autodesk's VLisp/VBA bridge, or something else.  Right now, I suspect the VLisp/VBA bridge, since not releasing the acad object doesn't cause a problem.  The vlax-get-acadObject method is probably hard-coded in a way that bypasses the general bridging mechanism, thereby bypassing the bug.

I'll let you know if I figure out anything else useful, but to be safe, I guess the only thing to do is to vla-release all vla-objects.  This is annoying, like Stig says, since not only does it mean you have to include a lot of otherwise unnecessary vla-release-object lines, it also means you can't inline vla- commands; in other words,

<plain english translation>

DON'T use constructs like:
(vla-get-name (vla-item (vla-get-documents (vlax-get-acad-object)) myIndex))

</plain english translation>

Instead, you have to assign the result of each vla- command to a local variable, so you can vla-release it later.  Blech!  :fart:

This is DEFINITELY something that should be in the documentation, in multiple places, underlined, in capital letters, quotated, with circles and arrows...