473,404 Members | 2,213 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,404 software developers and data experts.

How memory stacks up.

Hello, doing some profiling work and trying to resolve the memory usage
balooning through the roof. Just want to make sure that my reasoning is
correct.

My question is as follows: Let's say I have 1000 ArrayLists and each of
them has quite a bit of data in them. Does .NET framework load 1000
implementations of ArrayList in memory or does it load just one and uses
that to operate on data in the lists?

Thanks.
Nov 17 '05 #1
17 1169
Frank Rizzo <no**@none.com> wrote:
Hello, doing some profiling work and trying to resolve the memory usage
balooning through the roof. Just want to make sure that my reasoning is
correct.

My question is as follows: Let's say I have 1000 ArrayLists and each of
them has quite a bit of data in them. Does .NET framework load 1000
implementations of ArrayList in memory or does it load just one and uses
that to operate on data in the lists?


It only loads one implementation - the size of the JITted code is
usually much smaller than the size of the actual data used.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #2
Jon Skeet [C# MVP] wrote:
Frank Rizzo <no**@none.com> wrote:
Hello, doing some profiling work and trying to resolve the memory usage
balooning through the roof. Just want to make sure that my reasoning is
correct.

My question is as follows: Let's say I have 1000 ArrayLists and each of
them has quite a bit of data in them. Does .NET framework load 1000
implementations of ArrayList in memory or does it load just one and uses
that to operate on data in the lists?

It only loads one implementation - the size of the JITted code is
usually much smaller than the size of the actual data used.


However, by default, ArrayList instantiation, it allocates space for 16
entries. So I'd have 16*4*1000 bytes memory usage right out of the box,
correct? The 4 is 4 bytes for an empty object reference.
Nov 17 '05 #3
You can, of course, use

new ArrayList(1)

to initialize an arraylist with an initial capacity of 1 item.

Nov 17 '05 #4
Bruce Wood wrote:
You can, of course, use

new ArrayList(1)

to initialize an arraylist with an initial capacity of 1 item.


Yes, but I first want to analyze the existing memory pattern before
making changes to the code base.
Nov 17 '05 #5

"Frank Rizzo" <no**@none.com> wrote in message
news:en****************@TK2MSFTNGP10.phx.gbl...
Jon Skeet [C# MVP] wrote:
Frank Rizzo <no**@none.com> wrote:
Hello, doing some profiling work and trying to resolve the memory usage
balooning through the roof. Just want to make sure that my reasoning is
correct.

My question is as follows: Let's say I have 1000 ArrayLists and each of
them has quite a bit of data in them. Does .NET framework load 1000
implementations of ArrayList in memory or does it load just one and uses
that to operate on data in the lists?

It only loads one implementation - the size of the JITted code is usually
much smaller than the size of the actual data used.


However, by default, ArrayList instantiation, it allocates space for 16
entries. So I'd have 16*4*1000 bytes memory usage right out of the box,
correct? The 4 is 4 bytes for an empty object reference.


No the size of an Arralist is:
24 bytes fixed for the ArrayList + 32 bytes for the initial Object[] wrapped
by the ArrayList.
The array starts with 4 entries (16 bytes) and doubles it's size at each
extent.

So 1000 ArrayList's take 1000 * (32 + 24) = 56000 bytes.

Willy.


Nov 17 '05 #6

"Frank Rizzo" <no**@none.com> wrote in message
news:e3**************@TK2MSFTNGP10.phx.gbl...
Bruce Wood wrote:
You can, of course, use

new ArrayList(1)

to initialize an arraylist with an initial capacity of 1 item.


Yes, but I first want to analyze the existing memory pattern before making
changes to the code base.


Well this will account for a total (24 + 20) * 1000 = 44000 bytes.

Willy.
Nov 17 '05 #7
Frank Rizzo <no**@none.com> wrote:
It only loads one implementation - the size of the JITted code is
usually much smaller than the size of the actual data used.


However, by default, ArrayList instantiation, it allocates space for 16
entries. So I'd have 16*4*1000 bytes memory usage right out of the box,
correct? The 4 is 4 bytes for an empty object reference.


Aside from extra overhead, yes. But as Willy said, that's only a very
small amount of data. You'll be using much more memory up on your
*realy* data.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #8
> No the size of an Arralist is:
24 bytes fixed for the ArrayList + 32 bytes for the initial Object[] wrapped
by the ArrayList.
The array starts with 4 entries (16 bytes) and doubles it's size at each
extent.
It starts with 16 entries, not 4.
ms-help://MS.VSCC.2003/MS.MSDNQTR.2004JAN.1033/cpref/html/frlrfsystemcollectionsarraylistclassctortopic3.htm


So 1000 ArrayList's take 1000 * (32 + 24) = 56000 bytes.

Willy.

Nov 17 '05 #9
Gentlemen,

Just so that I understand... In terms of memory used by ArrayList
instantiations only, the following 2 structures will use up the same
amount of RAM? Forget the data, just empty instantiations.

Structure 1.

ArrayList singleList = new ArrayList(1000000);
Structure 2.
ArrayList [] multipleLists = new ArrayList [1000000];
for (int x=0;x<1000000;x++)
multipleLists[x] = new ArrayList(1);

Thanks
Jon Skeet [C# MVP] wrote:
Frank Rizzo <no**@none.com> wrote:
It only loads one implementation - the size of the JITted code is
usually much smaller than the size of the actual data used.


However, by default, ArrayList instantiation, it allocates space for 16
entries. So I'd have 16*4*1000 bytes memory usage right out of the box,
correct? The 4 is 4 bytes for an empty object reference.

Aside from extra overhead, yes. But as Willy said, that's only a very
small amount of data. You'll be using much more memory up on your
*realy* data.

Nov 17 '05 #10
Frank Rizzo <no**@none.com> wrote:
Just so that I understand... In terms of memory used by ArrayList
instantiations only, the following 2 structures will use up the same
amount of RAM? Forget the data, just empty instantiations.

Structure 1.

ArrayList singleList = new ArrayList(1000000);
Structure 2.
ArrayList [] multipleLists = new ArrayList [1000000];
for (int x=0;x<1000000;x++)
multipleLists[x] = new ArrayList(1);


Not at all.

The first has the overhead of 1 ArrayList object, and an array with
1,000,000 null references. That array will take 4MB + the overhead of
the array object itself (about 12 bytes IIRC).

The second has an array of references to start with (4MB+tiny
overhead), and then 1,000,000 ArrayList objects, each of which has its
own overhead (about 24 bytes, IIRC), and its own array (overhead + 4
bytes for the single null reference).

So, the difference is between just over 4MB, and about 40MB.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #11
Right, I was looking at v2.0 , on v1.x it defaults to 16 entries. (ArrayList
size = 24 + 16 + 64 = 104)
On v2.0 , the default is ... 0 entries, that is the object[] is created with
0 elements.
total size = ArrayList size 24 + Object[] size 16 = 40
, however the space reserved on the heap for the array is 32 bytes (4
entries), so while the object[] size is only 16 bytes, the real physical
size is 32. Whenever you add the first element to the list, the object[]
size becomes the real physical size (32).

Willy.

"Frank Rizzo" <no**@none.com> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl...
No the size of an Arralist is:
24 bytes fixed for the ArrayList + 32 bytes for the initial Object[]
wrapped by the ArrayList.
The array starts with 4 entries (16 bytes) and doubles it's size at each
extent.


It starts with 16 entries, not 4.
ms-help://MS.VSCC.2003/MS.MSDNQTR.2004JAN.1033/cpref/html/frlrfsystemcollectionsarraylistclassctortopic3.htm


So 1000 ArrayList's take 1000 * (32 + 24) = 56000 bytes.

Willy.


Nov 17 '05 #12
Jon Skeet [C# MVP] wrote:
Frank Rizzo <no**@none.com> wrote:
Just so that I understand... In terms of memory used by ArrayList
instantiations only, the following 2 structures will use up the same
amount of RAM? Forget the data, just empty instantiations.

Structure 1.

ArrayList singleList = new ArrayList(1000000);
Structure 2.
ArrayList [] multipleLists = new ArrayList [1000000];
for (int x=0;x<1000000;x++)
multipleLists[x] = new ArrayList(1);

Not at all.

The first has the overhead of 1 ArrayList object, and an array with
1,000,000 null references. That array will take 4MB + the overhead of
the array object itself (about 12 bytes IIRC).

The second has an array of references to start with (4MB+tiny
overhead), and then 1,000,000 ArrayList objects, each of which has its
own overhead (about 24 bytes, IIRC), and its own array (overhead + 4
bytes for the single null reference).

So, the difference is between just over 4MB, and about 40MB.


Ok, now I am confused. In the original answer to my question you stated
that .NET just loads one implementation of ArrayList, the rest is just
data. So according to you, the size of 2 structures should be about the
same. Because the first one is just a single ArrayList with allocated
memory for 1 million objects (4 bytes * 1 million). The second scenario
is an array of 1 million ArrayList objects (4mb + tiny overhead) + space
that each ArrayList object allocated (4 bytes) - so that's another 4MB.
And since you mentioned that .NET just loads one implementation of
ArrayList, that should be pretty much it.

Unless I misundertood your original answer.
Btw, you are absolutely correct, it is 4mb vs 40 mb (i just measured it).

Regards

Nov 17 '05 #13
Thanks, this is really helpful. My last question is how exactly did
figure out that the implementation of ArrayList is 24 bytes?

I am looking at ArrayList source code and it has the following local
variables which adds up to 39 bytes.

public virtual int Capacity { get; set; }
public virtual int Count { get; }
public virtual bool IsFixedSize { get; }
public virtual bool IsReadOnly { get; }
public virtual bool IsSynchronized { get; }
public virtual object this[int index] { get; set; }
public virtual object SyncRoot { get; }

// Fields
private const int _defaultCapacity = 0x10;
private object[] _items;
private int _size;
[NonSerialized]
private object _syncRoot;
private int _version;

Willy Denoyette [MVP] wrote:
Right, I was looking at v2.0 , on v1.x it defaults to 16 entries. (ArrayList
size = 24 + 16 + 64 = 104)
On v2.0 , the default is ... 0 entries, that is the object[] is created with
0 elements.
total size = ArrayList size 24 + Object[] size 16 = 40
, however the space reserved on the heap for the array is 32 bytes (4
entries), so while the object[] size is only 16 bytes, the real physical
size is 32. Whenever you add the first element to the list, the object[]
size becomes the real physical size (32).

Willy.

"Frank Rizzo" <no**@none.com> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl...
No the size of an Arralist is:
24 bytes fixed for the ArrayList + 32 bytes for the initial Object[]
wrapped by the ArrayList.
The array starts with 4 entries (16 bytes) and doubles it's size at each
extent.


It starts with 16 entries, not 4.
ms-help://MS.VSCC.2003/MS.MSDNQTR.2004JAN.1033/cpref/html/frlrfsystemcollectionsarraylistclassctortopic3.htm
So 1000 ArrayList's take 1000 * (32 + 24) = 56000 bytes.

Willy.


Nov 17 '05 #14

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP***********************@msnews.microsoft.co m...
Frank Rizzo <no**@none.com> wrote:
Just so that I understand... In terms of memory used by ArrayList
instantiations only, the following 2 structures will use up the same
amount of RAM? Forget the data, just empty instantiations.

Structure 1.

ArrayList singleList = new ArrayList(1000000);
Structure 2.
ArrayList [] multipleLists = new ArrayList [1000000];
for (int x=0;x<1000000;x++)
multipleLists[x] = new ArrayList(1);


Not at all.

The first has the overhead of 1 ArrayList object, and an array with
1,000,000 null references. That array will take 4MB + the overhead of
the array object itself (about 12 bytes IIRC).

The second has an array of references to start with (4MB+tiny
overhead), and then 1,000,000 ArrayList objects, each of which has its
own overhead (about 24 bytes, IIRC), and its own array (overhead + 4
bytes for the single null reference).

So, the difference is between just over 4MB, and about 40MB.

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


To be exect for v1.1 of the framework.

The ArrayList overhead is 24 bytes,
the Array overhead is 16 bytes.
So for 1 the total size is: 24 + 16 + (1.000.000 * 4) = 4.000.040 bytes.

For case 2:
An array of 1000000 entries of type ArrayList:
An array of 1.000.000 entries = 16 + (1.000.000 * 4)
plus..
1.000.000 ArrayLists with 1 entry
(24 + 20) * 1000000 = 44.000.000.
gives:
16 + (1.000.000 * 4) + (24 + 16 + 4) * 1000000 = 48.000.016

Willy.



Nov 17 '05 #15

"Frank Rizzo" <no**@none.com> wrote in message
news:e6**************@TK2MSFTNGP14.phx.gbl...
Thanks, this is really helpful. My last question is how exactly did
figure out that the implementation of ArrayList is 24 bytes?

I am looking at ArrayList source code and it has the following local
variables which adds up to 39 bytes.

public virtual int Capacity { get; set; }
public virtual int Count { get; }
public virtual bool IsFixedSize { get; }
public virtual bool IsReadOnly { get; }
public virtual bool IsSynchronized { get; }
public virtual object this[int index] { get; set; }
public virtual object SyncRoot { get; }

// Fields
private const int _defaultCapacity = 0x10;
private object[] _items;
private int _size;
[NonSerialized]
private object _syncRoot;
private int _version;


Wait a minute you are confusing implementation (behavior, that is the code)
and object state.
Code is loaded only once per type (not in the GC heap) , state is created
per instance of that type, right?

When talking about the object state, that is what is allocated on the GC
heap, we have per ArrayList:

- a fixed overhead of 8 bytes (2 words of 32 bits on X86) for each object
type, plus
- the object state consisting of: _items, _size, _syncRoot, _version; or 4
* 4 = 16 bytes
Makes 24 bytes.
BUT old on, the ArrayList wraps a Object[] _items as part of it's state, and
this array has:
16 bytes overhead + n * 4 bytes per Array element (4 bytes per element as
they are references), where n is 16 by default for a ArrayList().
Note that this is for empty arraylist only, add to that the real objects
added to the list .....
Willy.

Nov 17 '05 #16
Frank Rizzo <no**@none.com> wrote:
The first has the overhead of 1 ArrayList object, and an array with
1,000,000 null references. That array will take 4MB + the overhead of
the array object itself (about 12 bytes IIRC).

The second has an array of references to start with (4MB+tiny
overhead), and then 1,000,000 ArrayList objects, each of which has its
own overhead (about 24 bytes, IIRC), and its own array (overhead + 4
bytes for the single null reference).

So, the difference is between just over 4MB, and about 40MB.
Ok, now I am confused. In the original answer to my question you stated
that .NET just loads one implementation of ArrayList, the rest is just
data.


Yes.
So according to you, the size of 2 structures should be about the
same.
No, not at all. There's all the difference in the world between a
million arrays of length 1 (each of which is an object) and one array
of length a million.
Because the first one is just a single ArrayList with allocated
memory for 1 million objects (4 bytes * 1 million).
That's the space required just for the cost of the array of ArrayList
references, not for the ArrayLists themselves.
The second scenario
is an array of 1 million ArrayList objects (4mb + tiny overhead) + space
that each ArrayList object allocated (4 bytes) - so that's another 4MB.
The cost of each ArrayList object is more than 4 bytes - it's about 24
bytes: 8 bytes overhead for being an object, 4 bytes for the size, 4
bytes for the internal versioning, 4 bytes for the reference to the
array, and 4 bytes for the sync root reference. Then there's the
overhead of the array itself - 8 bytes for being an object, plus 4
bytes for the size, plus 4 bytes for the single reference (in the case
of a length 1 array). There may be other overheads in there.
And since you mentioned that .NET just loads one implementation of
ArrayList, that should be pretty much it.

Unless I misundertood your original answer.
Btw, you are absolutely correct, it is 4mb vs 40 mb (i just measured it).


Do you understand now? I'm not sure that I've listed anything above
that I didn't list in my previous post...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #17
Jon Skeet [C# MVP] wrote:
Frank Rizzo <no**@none.com> wrote:
The first has the overhead of 1 ArrayList object, and an array with
1,000,000 null references. That array will take 4MB + the overhead of
the array object itself (about 12 bytes IIRC).

The second has an array of references to start with (4MB+tiny
overhead), and then 1,000,000 ArrayList objects, each of which has its
own overhead (about 24 bytes, IIRC), and its own array (overhead + 4
bytes for the single null reference).

So, the difference is between just over 4MB, and about 40MB.


Ok, now I am confused. In the original answer to my question you stated
that .NET just loads one implementation of ArrayList, the rest is just
data.

Yes.

So according to you, the size of 2 structures should be about the
same.

No, not at all. There's all the difference in the world between a
million arrays of length 1 (each of which is an object) and one array
of length a million.

Because the first one is just a single ArrayList with allocated
memory for 1 million objects (4 bytes * 1 million).

That's the space required just for the cost of the array of ArrayList
references, not for the ArrayLists themselves.

The second scenario
is an array of 1 million ArrayList objects (4mb + tiny overhead) + space
that each ArrayList object allocated (4 bytes) - so that's another 4MB.

The cost of each ArrayList object is more than 4 bytes - it's about 24
bytes: 8 bytes overhead for being an object, 4 bytes for the size, 4
bytes for the internal versioning, 4 bytes for the reference to the
array, and 4 bytes for the sync root reference. Then there's the
overhead of the array itself - 8 bytes for being an object, plus 4
bytes for the size, plus 4 bytes for the single reference (in the case
of a length 1 array). There may be other overheads in there.

And since you mentioned that .NET just loads one implementation of
ArrayList, that should be pretty much it.

Unless I misundertood your original answer.
Btw, you are absolutely correct, it is 4mb vs 40 mb (i just measured it).

Do you understand now? I'm not sure that I've listed anything above
that I didn't list in my previous post...


Yes, thanks. I get it now. Something Willy said finally clicked in my
head. Code is loaded only once per type (not in the GC heap), state is
created per instance of that type. I grok it now. I have a object
model that has a lot of collections (array lists, hashtables) of other
collections. So I am having an effect where many thousand collection
objects get created each obviously consuming memory even though these
collections contain nothing. I will move those collections out as much
as possible to a higher-level object to alleviate the problem.

Regards
Nov 17 '05 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Frank Esser | last post by:
I am using SQL 8 Personal edition with sp2 applied. I set the max server memory to 32MB and leave the min server memory at 0. When my application starts hitting the database hard the memory usage...
16
by: Justin Lazanowski | last post by:
Cross posting this question on the recommendation of an I have a .NET application that I am developing in C# I am loading information in from a dataset, and then pushing the dataset to a grid,...
10
by: eyh5 | last post by:
Hi, My C code (running on Soalris Unix) has some "segmentation fault" that I wish to use purify to do it. I poked around the web, and found some information about adding some lines in a Makefile...
29
by: keredil | last post by:
Hi, Will the memory allocated by malloc get released when program exits? I guess it will since when the program exits, the OS will free all the memory (global, stack, heap) used by this...
13
by: hurry | last post by:
In order to avoid declaring static variables in a function I was asked to write a scratch memory. Reserve a block of memory outside the function and assigning pointers to the memory locations as...
15
by: syang8 | last post by:
hi, folks, I use Kdevelop to build some scientific simulation on Linux. If I set the size of an array N = 8000, the program works fine. However, if I set the array N some number greater than...
2
by: Daniel | last post by:
Hi, I have a question regarding the memory managment in stl stacks. I want to use stacks to store a very large amount of numbers (some millions), thus I'm interested in how the stack behaves...
1
by: Jonathan Wilson | last post by:
I am working on some software which has to deal with data that could be as large as 500mb or so. Currently I am using new and delete to manage this memory but I find it is not ideal and sometimes...
14
by: vivek | last post by:
i have some doubts on dynamic memory allocation and stacks and heaps where is the dynamic memory allocation used? in function calls there are some counters like "i" in the below function. Is...
11
by: Bryan Parkoff | last post by:
I want to know how much static memory is limited before execution program starts. I would write a large array. The large array has 65,536 elements. The data size is double word. The static...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.