Solved

VB Object size

Posted on 2000-05-16
33
523 Views
Last Modified: 2013-11-26
Ok, I heard an analysis of the collections and objects and the amount of memory they each take up in VB6 and I wonder if one of you guys has done this..As I cant find any documentation on it..

I heard that regardless of the amount of data in each class object they take 44kb for each object including 44Kb for each parent class that the object implements.

that they are improperly dropped from memory once all the referances to them are droped and the only way to ensure the removal is to destroy them i.e. set = nothing?

True or false, 50 to the first one with some proof either way on both points.

Not sure/dont know..then just comment.
0
Comment
Question by:wford
  • 12
  • 10
  • 3
  • +3
33 Comments
 
LVL 142

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 2814263
Creating an object (SET objVar = NEW ....) will do 2 things: Allocate your 44kb min on the heap, and set the reference counter to 1

Everytime you add a reference (ie SET objTemp = objVar) your reference counter will be increased by 1;

Everytime an object reference is destroied (SET objVar = NOTHING), either explicitely or implicitely, the counter will decrease by one.

If the counter hits 0, the object is definitively destroyed, ie removed from the help, the 44kb min are free.

This is object handling of ANY system (not only Windows/VB) as far as i know.

When you end an application (either END statement in VB or End Task in task manager), all the Inprocess objects will automatically be released, as all the [active] memory pages of the given application are freed

Hope this help

0
 

Expert Comment

by:monteh
ID: 2815077
Actually, 44KB is a bit excessive. Last I heard from Matt Curland was 52 bytes 2-3 years ago. While I'm sure it may have grown, certainly not to 44K; "probably" less than 100 bytes for the class itself. While not proof, bring up the TaskManager and watch your memory while executing this code:

Private Sub Form_Load()
    Dim X As Class1
    Set X = New Class1
End Sub


The bloat comes with all of the memory you may or may not allocate within the class.

To confirm what angelIII said, an object is destroyed when it's RefCont reaches 0, regardless of whether it was destroyed explicitly or simply went out of scope.
0
 
LVL 15

Expert Comment

by:ameba
ID: 2815368
>that they are improperly dropped from memory once all the referances to them are droped and the only way to ensure the removal is to destroy them i.e. set = nothing

This can happen sometimes (e.g. when there are circular references). It can be very unexpected, although this behaviour is by design.
0
 
LVL 2

Expert Comment

by:corvanderlinden
ID: 2816078
I am not sure but 44 kB looks a little bit excessive to me to

What you do with New (or CreateObject()) is (in my opinion)

1. allocate memory for a pointer to a COM interface
2. allocate memory for that COM interface (the vtable)
3. allocate memory for all other internals of the new class

If the reference count reaches zero, the object is dropped and all memory allocated by the object is released

In case of circular reference, the reference count does not reach zero unless you take some special action yourself
0
 
LVL 1

Author Comment

by:wford
ID: 2819318
thanks all..I have done the tests, but for some reason (most likely lack of enthusiasm) cant find precisely the memory allocated to each class or object..It seems to vary from 44Kb up and down the scale. Angel you say this is true for all object based systems eg Java?

and AngelIII if you are sure about that 44kb in VB,you can have the points

The ref system I knew about, but have had trouble with objects staying resident now and then, ameba..under what conditions do the objects stay with ref counter = 0, and example perhaps? Ill offer another 50 Q if you like.
0
 
LVL 15

Accepted Solution

by:
ameba earned 50 total points
ID: 2819632
50 pts Circular Reference sample :)
'-----------------------------------------------
' Form1 code
Option Explicit

Private Sub Form_Click()
    Dim x As Form2
    Set x = New Form2
    x.Show 1
    Set x = Nothing
End Sub

'-----------------------------------------------
' Form2, add Picturebox, paste this code to the form
Option Explicit
Private Border As cwBorder

Private Sub Form_Load()
    Set Border = New cwBorder
    Set Border.Pic = Picture1
    Border.Go
End Sub

Private Sub Form_Terminate()
' you shoud see this message when form is terminated
    MsgBox "Form Terminated"
End Sub

Private Sub Form_Unload(Cancel As Integer)
'     !!!!     Important     !!!!
' try running code with the next line commented
    Set Border = Nothing
' if the line is commented you won't see "Terminated" message
End Sub

'-----------------------------------------------
' class cwBorder, holds reference to its parent form
Option Explicit
Public Pic As PictureBox
Public WithEvents EvForm As Form
Private m_Active As Boolean

Private Sub EvForm_Resize()
    If m_Active Then Pic.Move 0, 0, EvForm.ScaleWidth, EvForm.ScaleHeight
End Sub

Public Sub Go()
    Set EvForm = Pic.Parent
    m_Active = True
End Sub
'
' Reference/explanation:
' http://www.vb2themax.com/HtmlDoc.asp?Table=Books&ID=100000
' see: Chapter 7, Page 349, multicasting
'
' Conclusion:
' EXPLICITLY set your objects to Nothing
' If you hope VB will do it for you when object variable
'    goes out of scope, you might be wrong
'-----------------------------------------------
0
 
LVL 2

Expert Comment

by:corvanderlinden
ID: 2820072
It is clear that circular references keep your objects alive if you do not use set obj = Nothing.
In this case it is that way because the reference count of Form2 will not reach 0 because Border keeps a reference to Form2 (Set EvForm = Pic.Parent) although Form1 sets Form2 to Nothing (which sets the reference count of Form2 from 2 to 1)

I always set my Objects to Nothing if I do not use them anymore and do not rely on VB to do it for me

I still wonder where you guys found out about the 44kB that every object allocates on the heap. Can somebody enlighten me, because to me it seems very unlikely and I never read something about it.

0
 
LVL 1

Author Comment

by:wford
ID: 2821010
thanks ameba..

corvanderlinden : I found out about it from proving tests we did on a project that was based on VB classes and objects..but the guy who did the test has forgotten the results and has left the company(as have I). We also had the discussion in french and I missed bits of it..so didnt get the full picture myself, hence the question.

The problem came because I got an out of memory error on a new object bassed program I have just done and I was worried that it was taking to much memory..turns out that the user had 5 MS word and Access programs running and they were sucking up most of the memory.
0
 
LVL 2

Expert Comment

by:corvanderlinden
ID: 2821018
Thanks
0
 
LVL 1

Author Comment

by:wford
ID: 2821044
AngelIII..if you answer the above query Ill post your 50 in a new question..

ameba..basicaly it is an implied referance to a parent object by a child object which stops the ref count = 0..ahhhh..
0
 
LVL 15

Expert Comment

by:ameba
ID: 2821126
wford, thanks for the points
And yes, 5 words can take a lot of memory.
0
 
LVL 142

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 2821513
Hmm, i have to apologize and admin that the value of 44kb is too high, and that i simply copied the value from your text (as i didn't know the exact value at all).

I did some tests too, and found that 16kb was used for an empty class (which is not of much use.
So for a class with (parent) properties we'll add some more bytes, so that 44 kb is still a realistic value.



0
 
LVL 1

Author Comment

by:wford
ID: 2827945
shame on you angel:)

yes this sort of agrees with my checks..the size seems to vary widly and size of code etc has little to do with it, I was realy looking for some concret reason/authority on why it takes up to 44Kb as opposed to 44bytes -1kb to store the object class..

If you can find that the points are yours.

As it is, I think I might have to fake up some psuedo classes with user defined types, but I am having trouble with passing them..ho hum
0
 
LVL 15

Expert Comment

by:ameba
ID: 2827965
Francesco Balena, Learn the major new features of VB6, VBPJ 12/98

"Interestingly, you can now use user-defined types (UDTs) as arguments or return values of public methods of public classes in ActiveX EXE or DLL projects. In other words, VB6's UDTs have become OLE-compliant data types that can be stored in a Variant variable and passed across processes. To exploit this new feature, you need to install DCOM98 on Windows 95/98, or the Service Pack 4 under Windows NT. This software is required on your customers' machines too, otherwise a runtime error occurs. (This is a problem only when passing UDTs across processes, because everything works fine with in-process components.)"

-----------

ameba EE 5/2000

To pass UDT, your project should be ActiveX (EXE/DLL/OCX). Your UDT declarations must be in a global class, e.g.:

' class2, set Instancing=6 'GlobalMultiUse
Option Explicit
Public Type Point
    X As Integer
    Y As Integer
End Type
0
 
LVL 142

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 2829301
I did not find the exact documentation about it, but i can explain it in some simple sentences (-:
Any class (object) is defined 3 main parts:
1) Data
2) Code
3) Interface
So every object has a minimal amount of space requirements due to it's data (the actual usage can vary, as more data is stored in the calls, ie variables sized strings or dynamic arrays)
The code however goes also in the memory, but is generally shared among all the instances of the class. So instantiating several objects of the same class will use less memory than simply multiplying the need of a single class...
Additionally, the interface definition(s) is also put into the memory. As every object (at least those from VB) implement several interfaces (IDispatch, IUnknown...).

So in short:
The more code you add to the class, the more space it will use in RAM.
The more Interfaces you implement, the more space it will use in RAM.
The more data you store in the object (=instance of class), the more space it will use in RAM

Next lession, you will learn about Early binding and Late binding
:-)

Cheers
0
 
LVL 1

Author Comment

by:wford
ID: 2829682
Yes, I know how the classes are built up..and the ones I use have been optiomised by implementing parent classes..the code functions are minimised using standard functions..and the data is the main thing..

But..some of my classes are simplt data holders and all they do is hold data and pass it back and forward..

So by using a single class collection storing a UDT lets say,I can maintain the object model, but save on class overheads that are not really needed..The only block is that UDTs cannot be passed in a variant of late binding..hence the need to make them an activeX and thus early binding to my projects.

At the moment I am tying a collection of standard data types that are passed by an interpretor function in a modual, if needed.

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 15

Expert Comment

by:ameba
ID: 2829712
>The only block is that UDTs cannot be passed in a variant of late binding

You can pass UDT As Variant.
0
 
LVL 1

Author Comment

by:wford
ID: 2829941
no, not in this instance

see:
http://support.microsoft.com/support/kb/articles/Q184/8/98.ASP

I have worked out most of the kinks in this method..but still have a problem with updating a collection item
0
 
LVL 15

Expert Comment

by:ameba
ID: 2830212
' I don't understand why MS sample uses 'As Object' to declare udt:
Private Sub Command1_Click()
   Dim obj1 As Object
   Dim obj2 As Object
   Set obj1 = CreateObject("TestServer.Class1")
   obj2 = obj1.MyMethod           '<== Generates run-time error #429.
End Sub

' If you change declaration to 'As Variant' everything works OK
Private Sub Command1_Click()
   Dim obj1 As Object
   Dim obj2 As Variant
   Set obj1 = CreateObject("TestServer.Class1")
   obj2 = obj1.MyMethod            ' works OK
   MsgBox obj2.y
End Sub


The second piece of code raises an error:
"Only user-defined types defined in public object modules can be coerced
to or from a variant or passed to late-bound functions."

So, to make it work, do not define UDT: in "Form1" and in "TestServer.Class1"
Put declaration in a public class (instancing=6), in the third, ActiveX DLL project "Project2"

' this works if both projects have reference to "Project2"
Private Sub Command2_Click()
   Dim obj1 As Object
   Dim mu As MyUDT
   Set obj1 = CreateObject("TestServer.Class1")
   mu = obj1.MyMethod            ' works OK
   MsgBox mu.y
End Sub
0
 
LVL 1

Author Comment

by:wford
ID: 2831630
funny you should post this..I was just working on it before I came on line..I was pretty positive it will work, but since it seems you tested it it should go fine.
Still there are some very strange things that I never knew about objects and collections, for instance you cannot modifiy an object once assigned to a collection, but you can modify its sub proporties..thus assigning a string to a collection stops you changing it..if you remove and re add it has problems with the object referance..baaahhhh..

simpler and (almost) as efficent to do what you noted above ameba
0
 
LVL 15

Expert Comment

by:ameba
ID: 2831684
Yes there are some strange things with objects...
Collections are slow, objects are 'heavy' (I am sorry your main question has not been answered, so we don't know 'the weight')
When performance is important we must use 'not so cool' arrays and UDTs, instead of objects.
0
 
LVL 1

Author Comment

by:wford
ID: 2832235
I'm seeing that ..would you belive the method above works fine until you try and adjust the values of an UDT sub value..then it simply refuses to budge..no errors ,no fouls, just no change(I imagine the whole UDT structure is seen as an object and thus cannot be changed, but since you are not changing the objects primary structure/pointer then no errors are called)
So I am going to bight the ugly code bullet and store them in arrays of UDTs..all wraped up to look like a collection of UDTs.

the remove method is ugly but as I never use it I may simply dump it.
0
 

Expert Comment

by:monteh
ID: 2833891
The problem you describe is a result of the UDT being passed quasi "ByVal"; that is a copy of the UDT is being passed, not a pointer. This can be proven by doing a debug.print VarPtr(myUDT) before and after it is passed -- you will get a different address.

Checkout the linked list class on my Classes page at http://killervb.com. It demonstrates what you are trying to do. All data is held within a UDT array by the parent 'LinkedList' class. The child 'LinkedListItem' class is but a shell or interface to get to the data. Child classes are created only on demand as needed rather than storing a ton of them in a collection. It's interface is much like the TreeView's Nodes collection.

Hope this helps.
0
 
LVL 1

Author Comment

by:wford
ID: 2835575
thanks monteh..

The item/collection system is what I have used before, but the consideration was memory and speed.

I'll explain:

I have an anyobject class that the whole of my program is bassed on..it is the basic description of a database object. to that object I tack a collection of attributes as and if needed, the power of this method is such that I can change the database design and add or remove attributes in my program without recompiling.

However, each of these attribute collections take up alot of space for what is basically an array of UDT's, unlike the anyobjects they have no functions and no methods..thus the essence of this question..is it worth replacing a working system with a smaller faster one.  
0
 

Expert Comment

by:monteh
ID: 2837756
Probably not. If it works fine and no one is complaining.

It's our nature to want to improve our designs. I cant tell you how many times I've rolled something out and later discovered a better way (or during the course of development). I just keep it in mind -- maybe I'll get to rewrite it, and maybe not.

Cheers,

Monte
0
 
LVL 15

Expert Comment

by:ameba
ID: 2838318
>is it worth replacing a working system with a smaller faster one
There is not enough data to answer this.
If you can create simple sample (1 table) of your working system, maybe this can be optimized.

>the power of this method is such that I can change the database design and add or remove attributes in my program without recompiling.

Sounds cool, but if you add one field to the table, you'll have to do some compiling when you add a textbox for that field, right? Any more info on this interesting concept. (I also have some ee points to see 'anyobject' class)
0
 
LVL 1

Author Comment

by:wford
ID: 2840622
you'll have to do some compiling when you add a textbox for that field

yes perhaps..but the text boxes all have there datafields property set to the attribute field name..and all the forms loads simply look for that field name key in the attributes collection..so except for adding the text box..there is no other coding to be done. This allows the program to be paramiterised very simply, and all the attributs have language components so the whole application can have a new language added or removed without recompiling..

as for the any object parent class, all the objects know there parent..and a set of relations govern what can be parents and children..and a set of functions can be executed and attributes returned..in essence it is simply the windows file system jigged up.


Public Function GetAttributes(attrcoll As AttrCollection, Optional refresh As Boolean = False) As Integer

End Function
Public Function SetAttributes() As Integer

End Function

Public Property Let Status(ByVal vdata As Integer)

End Property
Public Property Let ParentID(ByVal vdata As Long)

End Property

Public Property Get ParentID() As Long

End Property
Public Property Let ParentType(ByVal vdata As String)

End Property

Public Property Get ParentType() As String

End Property

Public Property Get Status() As Integer

End Property


Public Property Let Image(ByVal vdata As String)

End Property

Public Property Get Image() As String

End Property

Public Property Let Visible(ByVal vdata As Boolean)

End Property


Public Property Get Visible() As Boolean

End Property



Public Property Let Name(ByVal vdata As String)

End Property


Public Property Get Name() As String

End Property



Public Property Let ItemType(ByVal vdata As String)

End Property


Public Property Get ItemType() As String

End Property



Public Property Let ItemID(ByVal vdata As Long)

End Property


Public Property Get ItemID() As Long

End Property
Public Property Let Lookup(ByVal vdata As String)

End Property

Public Property Get Lookup() As String

End Property
Public Property Let Key(ByVal vdata As String)

End Property


Public Property Get Key() As String

End Property
Public Sub Execute(Optional Skey As String = "")
'calls function code based on object
End Sub
0
 
LVL 15

Expert Comment

by:ameba
ID: 2841972
Thanks, wford (see www.experts-exchange.com/jsp/qShow.jsp?ta=visualbasic&qid=10355832 )

>it is the basic description of a database object
I am not sure I understand if this class is used for Table or you add instance of this class for each Field.

My guess is you have separate class, similar to one you show, for each table.
I thought
   Execute(Optional Skey As String = "")
is used to Delete, ..., but then it should have some argument like ActionType
Any more info, please...

Thanks
0
 
LVL 15

Expert Comment

by:ameba
ID: 2851641
OK, no problem.
0
 

Expert Comment

by:AA69
ID: 6164072
How do you pass a UDT as a Variant then?
0
 
LVL 15

Expert Comment

by:ameba
ID: 6164120
AA69
> How do you pass a UDT as a Variant
Your UDT must be defined in public class module
e.g. in class with instancing=6 - for this, your project must be ActiveX .Exe or ActiveX .Dll

You can pass UDTs as parameters in standard Exe project, if your function is Friend:
>public function GetMessage(UDT as someUDT)
Friend function GetMessage(UDT as someUDT)
0
 
LVL 15

Expert Comment

by:ameba
ID: 6164176
Actually, it is explained after my comment "You can pass UDT As Variant", but comments are not sorted 'by time' (ee bug).
-------------------------------------------------------
Comment
From: ameba  Date: 05/20/2000 06:29PM PST  
>The only block is that UDTs cannot be passed in a variant of late binding

You can pass UDT As Variant.  
-------------------------------------------------------
Comment
From: wford  Date: 05/20/2000 10:53PM PST  
no, not in this instance

see:
http://support.microsoft.com/support/kb/articles/Q184/8/98.ASP

I have worked out most of the kinks in this method..but still have a problem with updating a collection
item  
-------------------------------------------------------
Comment
From: ameba  Date: 05/21/2000 03:19AM PST  
' I don't understand why MS sample uses 'As Object' to declare udt:
Private Sub Command1_Click()
  Dim obj1 As Object
  Dim obj2 As Object
  Set obj1 = CreateObject("TestServer.Class1")
  obj2 = obj1.MyMethod           '<== Generates run-time error #429.
End Sub

' If you change declaration to 'As Variant' everything works OK
Private Sub Command1_Click()
  Dim obj1 As Object
  Dim obj2 As Variant
  Set obj1 = CreateObject("TestServer.Class1")
  obj2 = obj1.MyMethod            ' works OK
  MsgBox obj2.y
End Sub


The second piece of code raises an error:
"Only user-defined types defined in public object modules can be coerced
to or from a variant or passed to late-bound functions."

So, to make it work, do not define UDT: in "Form1" and in "TestServer.Class1"
Put declaration in a public class (instancing=6), in the third, ActiveX DLL project "Project2"

' this works if both projects have reference to "Project2"
Private Sub Command2_Click()
  Dim obj1 As Object
  Dim mu As MyUDT
  Set obj1 = CreateObject("TestServer.Class1")
  mu = obj1.MyMethod            ' works OK
  MsgBox mu.y
End Sub
0
 

Expert Comment

by:AA69
ID: 6164586
Thanks for your comment back ameba I have just posted a question that relates to this problem I am offering 200 points for an answer and would be glad to give you them if you can answer it for me.

This is a bit of a problem for me as I want to run under COM+,  and MS say you must not use Global multiclasses for this as it holds state.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now