Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Performance / January 2005

Tip: Looking for answers? Try searching our database.

How much memory do managed code objects take, really?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Marcos Stefanakopolus - 07 Jan 2005 17:31 GMT
Is there a general method for finding out, to the byte, how much memory is
consumed by a given instance of an object?

I'm in the process of designing a scientific simulation program (to simulate
planetary formation, tectonics, etc).  To simulate an earth-sized planet
with any nice degree of resolution takes an astonishing number of objects.
For instance, tiling the earth with triangles of size 50 kilometers just to
do a reasonable tectonic simulation takes almost 440,000 triangles.  That's
not bad, but subsequent refinements down to 1 km blow that number up to
something like 1.7x10^9 triangles (or maybe only 6x10^8 if I ignore
everything that's underwater).

Clearly, in this type of application, every byte of memory must be carefully
considered; even a single extra byte of padding somewhere in a data
structure can end up costing you hundreds of MB of memory.  I need to decide
whether to implement these triangles and their vertices as managed C#
objects (much easier for me), or as unmanaged C++ objects (in order to
tightly control memory so the model fits into RAM).

In the unmanaged C++ world, I know exactly how to count the bytes my classes
will take up.  In the managed C# world, with the overhead that the framework
imposes in order to be able to move objects around, do garbage collection,
etc., I have no idea.  If I define:

class WorldPoint {
 public float x,y,z;        // in C++ this costs 12 bytes
}

class WorldTriangle {
 WorldPoint *vertices[3];    // in C++, this costs 12 bytes, too, in the
form of pointers.
}

In C++, if I build 1 WorldTriangle, I've used 12 bytes for pointers to the
vertices, and 36 bytes for the vertex objects themselves.  In C#, How much
memory have I really used?
Jon Skeet [C# MVP] - 07 Jan 2005 21:07 GMT
> Is there a general method for finding out, to the byte, how much memory is
> consumed by a given instance of an object?

The method I usually use is to create a test program which creates an
empty array of hundreds of thousands of references, finds out the
amount of memory used, fills in the array with hundreds of thousands of
objects, finds out the amount of memory *then* used, and then looks at
the difference between the two. Use GC.KeepAlive to make sure the array
(and thus the instances) don't get collected.

You can also work it out manually for simple cases, of course.

<snip>

> In the unmanaged C++ world, I know exactly how to count the bytes my classes
> will take up.  In the managed C# world, with the overhead that the framework
[quoted text clipped - 13 lines]
> vertices, and 36 bytes for the vertex objects themselves.  In C#, How much
> memory have I really used?

Each object has an overhead of 8 bytes. Each float takes 4 bytes. Each
reference takes 4 bytes. Each one-dimensional array takes the size of
the element * number of elements + 16 bytes (I *think* - check that, as
there could be more stuff I've missed, particularly for non-zero lower
bounds).

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Jon Skeet [C# MVP] - 07 Jan 2005 21:12 GMT
<snip>

> > In C++, if I build 1 WorldTriangle, I've used 12 bytes for pointers to the
> > vertices, and 36 bytes for the vertex objects themselves.  In C#, How much
[quoted text clipped - 5 lines]
> there could be more stuff I've missed, particularly for non-zero lower
> bounds).

Sorry, I meant to mention - there are also potential gaps due to
padding between elements. That is variable depending on the layout used
- which is one reason to test your estimate using a program.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Marcos Stefanakopolus - 07 Jan 2005 23:50 GMT
>> The method I usually use is to create a test program which creates an
>> empty array of hundreds of thousands of references, finds out the
>> amount of memory used, fills in the array with hundreds of thousands of
>> objects, finds out the amount of memory *then* used, and then looks at
>> the difference between the two.

And how do you do the "finds out the amount of memory used" part?  Do you
have some code you could share?  Somehow I doubt that what Task Manager will
tell me is either precise or accurate enough.

>> > In C++, if I build 1 WorldTriangle, I've used 12 bytes for pointers to
>> > the
[quoted text clipped - 4 lines]
>> Each object has an overhead of 8 bytes. Each float takes 4 bytes. Each
>> reference takes 4 bytes.

So you're saying that all reference types have an 8-byte overhead, while
value types have a 0 byte overhead?  If true, that's probably sufficient for
my purposes.

> Sorry, I meant to mention - there are also potential gaps due to
> padding between elements.

Yes, I'm aware of that potential issue.  Fortunately, there's
[StructLayoutAttribute(LayoutKind.Explicit)] to help with that.
Jon Skeet [C# MVP] - 08 Jan 2005 07:38 GMT
> >> The method I usually use is to create a test program which creates an
> >> empty array of hundreds of thousands of references, finds out the
[quoted text clipped - 5 lines]
> have some code you could share?  Somehow I doubt that what Task Manager will
> tell me is either precise or accurate enough.

GC.GetTotalMemory.

> >> > In C++, if I build 1 WorldTriangle, I've used 12 bytes for pointers to
> >> > the
[quoted text clipped - 8 lines]
> value types have a 0 byte overhead?  If true, that's probably sufficient for
> my purposes.

That's true - but don't forget that if a value type taking, say, 12
bytes and you have 5 copies of it (60 bytes in total), you'd be better
off with 5 references (20 bytes) and one instance (20 bytes).

I almost never use memory usage to decide whether to use reference
types or value types though - normal semantics should almost always
dictate that.

> > Sorry, I meant to mention - there are also potential gaps due to
> > padding between elements.
>
> Yes, I'm aware of that potential issue.  Fortunately, there's
> [StructLayoutAttribute(LayoutKind.Explicit)] to help with that.

Yup. (Not sure why it's named StructLayoutAttribute when it can apply
to classes, but never mind.)

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Bruno Jouhier [MVP] - 08 Jan 2005 08:17 GMT
>> >> The method I usually use is to create a test program which creates an
>> >> empty array of hundreds of thousands of references, finds out the
[quoted text clipped - 33 lines]
> types or value types though - normal semantics should almost always
> dictate that.

Right! Two more reasons to follow normal semantics (unless you have a very
good reason to do otherwise) :

If you want to use references and share instances to benefit from the memory
savings, you need some kind of indexing mecanism (hash table, array) to
"intern" identical values and produce a unique reference. So, you have to
take this into account in your memory computation.

When you run on a 64 bit OS, the pointers will double in size!

Bruno.

>> > Sorry, I meant to mention - there are also potential gaps due to
>> > padding between elements.
[quoted text clipped - 4 lines]
> Yup. (Not sure why it's named StructLayoutAttribute when it can apply
> to classes, but never mind.)
Marcos Stefanakopolus - 10 Jan 2005 20:41 GMT
>> And how do you do the "finds out the amount of memory used" part?  Do you
>> have some code you could share?  Somehow I doubt that what Task Manager
>> will
>> tell me is either precise or accurate enough.
>
> GC.GetTotalMemory.

Beautiful, thanks!

>> So you're saying that all reference types have an 8-byte overhead, while
>> value types have a 0 byte overhead?  If true, that's probably sufficient
[quoted text clipped - 4 lines]
> bytes and you have 5 copies of it (60 bytes in total), you'd be better
> off with 5 references (20 bytes) and one instance (20 bytes).

Can't I have the best of both worlds?  If I make my vertex type a value
type, and go to the bother of working with references explicitly in my
triangle class, wouldn't I end up with (in your example) 12+20 bytes rather
than 20+20?  If there's some subtle reason why not, please let me know.

> I almost never use memory usage to decide whether to use reference
> types or value types though - normal semantics should almost always
> dictate that.

Do you regularly work with applications that have quantities of objects best
expressed in exponential notation?  :-)

>> > Sorry, I meant to mention - there are also potential gaps due to
>> > padding between elements.
[quoted text clipped - 4 lines]
> Yup. (Not sure why it's named StructLayoutAttribute when it can apply
> to classes, but never mind.)

If I had to guess, I'd say it's because they created it for the purpose of
making C# structs also support C-style union semantics, but then realized
that there was no particular reason why that attribute couldn't also apply
to classes.
Jon Skeet [C# MVP] - 10 Jan 2005 22:46 GMT
> > That's true - but don't forget that if a value type taking, say, 12
> > bytes and you have 5 copies of it (60 bytes in total), you'd be better
[quoted text clipped - 4 lines]
> triangle class, wouldn't I end up with (in your example) 12+20 bytes rather
> than 20+20?  If there's some subtle reason why not, please let me know.

If you make Vertex a value type, you could sort of get the best of both
worlds by using Object when you want to use it as a sort of reference
type - so it causes boxing - or you might want to have both a struct
and a class which just contains the struct as its only field. That way
you could explicitly say in your code which you wanted to use at any
one time.

> > I almost never use memory usage to decide whether to use reference
> > types or value types though - normal semantics should almost always
> > dictate that.
>
> Do you regularly work with applications that have quantities of objects best
> expressed in exponential notation?  :-)

No - that's why I didn't express is as an absolute rule :)

> > Yup. (Not sure why it's named StructLayoutAttribute when it can apply
> > to classes, but never mind.)
[quoted text clipped - 3 lines]
> that there was no particular reason why that attribute couldn't also apply
> to classes.

Possibly. It's far from the worst decision in the framework, of course
:)

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.