?
Solved

Memory usage

Posted on 2004-11-05
9
Medium Priority
?
259 Views
Last Modified: 2010-04-05
Hi,

Does anyone know for sure how much more memory a TObject instance allocates then if it is declared as simple record?

Regards, CC.

0
Comment
Question by:cc042297
  • 4
  • 2
  • 2
  • +1
9 Comments
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12506557
About 100 to 200 bytes more, depending on the Delphi version. Every object has some additional overhead pointing to the related virtual method table and for some additional internal data. An exact value isn't easy to provide since there's a dependency on the exact class type. Objects are more expensive in memory usage so if you need to save memory, don't use them. (Or buy more RAM, which is what I always advise my customers...)
0
 

Author Comment

by:cc042297
ID: 12506612
Hi Alex!

Just to make sure I got it wright: EVERY instance of a TObject uses 100 to 200 bytes? .... that is much more than I expected!  
0
 

Author Comment

by:cc042297
ID: 12507088
I have tried to make a rough estimation with the help of Win XP's taskmanager. I created 1.000.000 instance of a record, and the same amount of an object. They both had only 2 integer fields. If taskmanager is correct the average difference is around 4 bytes per instance ...
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 6

Expert Comment

by:vadim_ti
ID: 12507201
I do not think you will have a big overhead, because overhead will be on class level and not on instance level

you can see it with memproof

declare class and begin create instances of this class and do not free them.
you will see there are no overhead
0
 

Author Comment

by:cc042297
ID: 12509164
I have taken a look at TObject's declaration and some of the methods and class methods and from there I had the same impression. I just did not know if the compiler adds anything else.

 "you can see it with memproof" - Is 'memproof' a program?  Never heard of. ;)
0
 
LVL 6

Expert Comment

by:vadim_ti
ID: 12509187
memproof is a free development tool

its main use is to test application for memory leaks
you can google for memproof
0
 
LVL 6

Accepted Solution

by:
gwalkeriq earned 400 total points
ID: 12510386
Objects are not much different in size than the equivalent record, the only difference being enough RTTI for to identify the object type (a single pointer type IIRC). There is no object data in the TObject class, but the virtual methods and RTTI fnctions require a simple simple and fast method to do track thinks on a per-object basis, which is fortunately the VMS in both bases.

It is nearly impossible to confirm this however, since the Delphi compiler itself is closed source. However, if you call the InstanceSize method on an object that has not other data you will see that the size if 4 bytes., and if you look at TObject.InitInstance() in the system uint you come real close to confirming this -- unless you assume Borland goes to devious extremes to hide the implmentation

There is a 1-time charge for the vtable needed for each different class, this is roughly 100 bytes (92 with D6, see the Virtual Table Method Entries in the system unit).

However, there is a potentially huge difference in the Objects are allways allocated from the heap. Each time you create an object using the generic heap allocation. The amount of wasted slack and memory fragmentation this produced complicates the memory use issue considerably. At a minimum, most generic allocators add an extra negative offset header that  lets the deallocator know how big the memory block is -- have not disassembled Borland manager, but it could use the value from the VTBL instead a using the underlying generic memory allocator. However, there is a bigger problem in that generic allocators do not allow random allocate / free patterns without introducing extra memory (and cpu) overhead because of this. I've read before that the Delphi heap manager only managers a since heap, so in a program with lots of objects of different sizes you are liable to get lots of fragmentation and slack (both of which are bad)

If you are allocating 1 million objects, it's probably a real good idea to use a private memory allocator (see the NewInstance / FreeInstance methods of TObject). Though I've not done this with Delphi, I've used private class allocators in C++ programs with millions of objects and have seen significant memory & performance gains.

My take on this would be, its 4 bytes (or more), but if you are willing to write the private allocator, you can essentially guarantee that you only have 4 additional bytes of overhead.

An easier approach is to get a better memory allocator than the one Borland uses, I seem to recall that there is one, but it may be defunct since I can't find it with a couple of obvious Googles.
0
 
LVL 17

Assisted Solution

by:Wim ten Brink
Wim ten Brink earned 100 total points
ID: 12513863
A TObject is actually just a pointer to a memory location, thus 4 bytes. If the object is created, the object points to some allocated piece of memory containing the data. However, Delphi also maintains some additional type information at that location. A pointer to the VMT table of the object and I think another pointer to the Interface table. (for support of interfaces) These tables do require a small amount of memory for every classtype, not for every object.

But the best way to get this info is by using this project with Delphi 7:

program Project7;
{$APPTYPE CONSOLE}
var
  AnObject: TObject;
begin
  WriteLn('Memory in use: ', AllocMemSize);
  AnObject := TObject.Create;
  WriteLn('Memory in use: ', AllocMemSize);
  AnObject.Free;
  Write('Press <Enter> to quit.');
  WriteLn('Memory in use: ', AllocMemSize);
  ReadLn;
end.

AllocMemSize tells how much the Delphi memory manager has allocated in memory. Before the object is created, it is 0. When created, it went up to 8 and thus suggesting it has stored two pointers. After freeing, it is back to 0. Since TObject doesn't contain any data, it must be something that provides type information for the objects. Records just don't have any type information.
That TObject contains a pointer for a reference to an interface table became clear to me when I used "AnObject := TInterfacedObject.Create;" to create an interfaced object. TInterfacedObject contains one data element, a reference counter, and indeed the memory usage went up to 12 bytes. Exactly the size of the reference counter. But it must support the interface usage thus TObject itself supports interfaces from the basics.

In older Delphi versions the amount of memory usage might be a lot lower. I'm not 100% sure but I believe that with the older Delphi versions, every object had it's own VMT allocated with the object allocation itself. I just can't test it anymore...

Thus, the size of objects is:
4 bytes per object for a pointer to the Virtual Memory table.
4 bytes per object for a pointer to the Interface table.
About 100 bytes per class for the Virtual Memory table.
An unknown amount per class for the Interface table.
And if you have a pointer pointing at the object, an additional 4 bytes for the pointer.
Plus the size of the data elements in the object.

The size for a record is just the size of the data elements and not a byte more. Unless you have a pointer to a record in which case you have an additional 4 bytes for the pointer.

With records, pointers are optional to get access to the data. If the record is declared as global or local variable then Delphi knows the exact location of the data thus doesn't need the address. But with objects, you always get a pointer pointing to some other address.
0
 

Author Comment

by:cc042297
ID: 13193589
Thanx Experts!
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
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…
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Suggested Courses

840 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