get object size C#

A

ApeX

Is there a way to get size of an object stored in memory?

I have an xmldocument which i fill with the some data, and just before
i call the Save method, i wanna get
the number of bytes that xmldocument is using in memory?

Thanx!
 
S

Stanimir Stoyanov

Regarding the XmlDocument case, you can first save it to a MemoryStream and
retrieve its Length value. The stream will then be disposed automatically if
you use the 'using' syntax:

using (MemoryStream stream = new MemoryStream())
{
xmlDoc.Save(stream);

// Do something with stream.Length. You can also
write the stream bytes to your file instead of calling Save again.
}
 
S

Stanimir Stoyanov

P.S. > Is there a way to get size of an object stored in memory?

There is no single answer to this part of your question. You have to
consider value and reference types.

The amount of memory occupied by value types such as integral values or
structures can be easily predicted because their size is fixed. You can do
so by calling System.Runtime.InteropServices.Marshal.SizeOf against the type
or the particular value.

Regarding reference types, there is no unified way to get an object's size.
For example, an the representation of an XmlDocument in memory is not
textual (as it is written on disk) but a tree of nodes, each containing its
relevant data. Only after the data is "flattened", can you 'observe' its
size. Encodings take a significant part here too--a character in ASCII is 1
byte long while Unicode uses two or even more bytes to represent a single
character.
 
J

Jeff Johnson

Is there a way to get size of an object stored in memory?

I have an xmldocument which i fill with the some data, and just before
i call the Save method, i wanna get
the number of bytes that xmldocument is using in memory?

I take it XmlDocument.InnerXml.Length is not what you're looking for?
 
N

Nicholas Paldino [.NET/C# MVP]

Mind you, that this is the length of the representation of the info set
encoded as text, it is NOT the size of the object. The document has
internal structures that it is using to store the infoset in memory and it's
not directly analagous to the representation of the infoset in text.

I assume that the length of the infoset encoded as text is what the OP
wanted, but the difference is worth pointing out, IMO.
 
S

Stanimir Stoyanov

I agree, Nicholas, I described this in my second reply to the OP. In this
case, there is no (easy?) way to determine the amount of memory occupied by
a given object of reference type.
--
Stanimir Stoyanov
http://stoyanoff.info

Nicholas Paldino said:
Mind you, that this is the length of the representation of the info set
encoded as text, it is NOT the size of the object. The document has
internal structures that it is using to store the infoset in memory and
it's not directly analagous to the representation of the infoset in text.

I assume that the length of the infoset encoded as text is what the OP
wanted, but the difference is worth pointing out, IMO.
 
N

Nicholas Paldino [.NET/C# MVP]

Stanimir,

Without hooking into the CLR, there doesn't seem to be an easy way to do
this.

Curious, for what purpose do you want to see this?

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Stanimir Stoyanov said:
I agree, Nicholas, I described this in my second reply to the OP. In this
case, there is no (easy?) way to determine the amount of memory occupied by
a given object of reference type.
--
Stanimir Stoyanov
http://stoyanoff.info

Nicholas Paldino said:
Mind you, that this is the length of the representation of the info
set encoded as text, it is NOT the size of the object. The document has
internal structures that it is using to store the infoset in memory and
it's not directly analagous to the representation of the infoset in text.

I assume that the length of the infoset encoded as text is what the OP
wanted, but the difference is worth pointing out, IMO.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Stanimir Stoyanov said:
Regarding the XmlDocument case, you can first save it to a MemoryStream
and retrieve its Length value. The stream will then be disposed
automatically if you use the 'using' syntax:

using (MemoryStream stream = new MemoryStream())
{
xmlDoc.Save(stream);

// Do something with stream.Length. You can also
write the stream bytes to your file instead of calling Save again.
}
--
Stanimir Stoyanov
http://stoyanoff.info

Is there a way to get size of an object stored in memory?

I have an xmldocument which i fill with the some data, and just before
i call the Save method, i wanna get
the number of bytes that xmldocument is using in memory?

Thanx!
 
G

Göran Andersson

ApeX said:
Is there a way to get size of an object stored in memory?

I have an xmldocument which i fill with the some data, and just before
i call the Save method, i wanna get
the number of bytes that xmldocument is using in memory?

It's impossible to give an exact amount for that.

Consider this example:

string[] x = {
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
"This is a string value containing quite some characters.",
};

You would think that the array would use about 1300 bytes, but it
doesn't. The array doesn't contain ten references to ten separate
strings, it contains ten references to the same string, so it's using
about 160 bytes. Or, if you consider that the string is not created just
for the array but is a constant in the assembly, it's only using about
50 bytes.

(Memory sizes mentioned assuming a 32-bit system.)

So, you can't just add up what an object references and say that this is
the size. Also it depends on if you mean:

1. The amount of memory that is used to hold everyting for the object.
2. The amount of memory saved if you didn't create the object.
3. The amount of memory needed to create the object.
4. The amount of memory needed to create another copy of the object.

Those can all end up being different amounts...
 
A

ApeX

Curious, for what purpose do you want to see this?

I have a datatable which through i loop, and add data to the
xmldocument accordingly. The problem is that the max size of the
xmldocument must be 500kb, and if it's larger than that then the file
must be broken into several files. Another problem is that each new
created file must be well xml formatted.

So, i need to find out when the file is exceeding 500kb, and then
write a file with the processed data, and then make another file or
files with the remaining data if it doesn't exceed 500kb, and etc.
etc..
 
G

Göran Andersson

ApeX said:
I have a datatable which through i loop, and add data to the
xmldocument accordingly. The problem is that the max size of the
xmldocument must be 500kb, and if it's larger than that then the file
must be broken into several files. Another problem is that each new
created file must be well xml formatted.

So, i need to find out when the file is exceeding 500kb, and then
write a file with the processed data, and then make another file or
files with the remaining data if it doesn't exceed 500kb, and etc.
etc..

Then you were not asking for what you wanted.

The amount of memory that the XmlDocument is using is not the length of
the file when you write it out as XML. The elements are stored
completely different in memory.

Have a look at the OuterXml property of the XmlNode object.
 
M

Manu

Then you were not asking for what you wanted.

The amount of memory that the XmlDocument is using is not the length of
the file when you write it out as XML. The elements are stored
completely different in memory.

Have a look at the OuterXml property of the XmlNode object.

But a very interesting discussion was started by this topic.
 
S

Stanimir Stoyanov

The length of the OuterXml string will not necessarily reflect the length of
the data *on disk* depending on the encoding used when saving.

I think it would be a better idea to save the xml document to a MemoryStream
and then check its length, as proposed in my first reply to the OP.
 
A

Anthony Jones

Stanimir Stoyanov said:
The length of the OuterXml string will not necessarily reflect the length
of the data *on disk* depending on the encoding used when saving.

I think it would be a better idea to save the xml document to a
MemoryStream and then check its length, as proposed in my first reply to
the OP.

A far better approach would be to ditch XmlDocument altogether.

Create XmlTextWriter on a BufferedStream on a FileStream.

Use XmlTextWriter to create the Xml as needed which will just stream out the
destination file, the BufferedStream Length property would tell you exacly
how much has been written to the file.

When appropriate the existing content can be closed off and a new pair of
streams and a writer could be created to continue with the next traunch of
content and so on.

This approach allows you to accurately monitor the size of XML file being
created, doesn't require frequent large strings to be generated and dropped
(as using OuterXml.Length would do) and limits the demand for memory in the
application (memory requirements limited to the size of buffer choosen when
creating the BufferedStream).
 
N

not_a_commie

I think it would be a better idea to save the xml document to a
A far better approach would be to ditch XmlDocument altogether.

Create XmlTextWriter on a BufferedStream on a FileStream.

I'm not sure you need to ditch the XmlDocument object. However, I
absolutely agree that a MemoryStream is almost never what you want
when dealing with XML. It will add byte markers to the start of the
stream. You should write out your documents this way:

using (var writer = new XmlTextWriter(filename, new UTF8Encoding
(false)))
{
writer.Formatting = Formatting.Indented;
xmlDoc.Save(writer);
writer.Close();
}
 
G

Göran Andersson

Stanimir said:
The length of the OuterXml string will not necessarily reflect the
length of the data *on disk* depending on the encoding used when saving.

Yes, I ment to mention that, but I forgot. :)

It may also differ depending on how the XML code is indented.
I think it would be a better idea to save the xml document to a
MemoryStream and then check its length, as proposed in my first reply to
the OP.

That way you will only know if the documnet is too large or not, it will
not tell you how many nodes you can put in each file.

I would get the XML code for each node, encode into a byte array and
write to the file. That way you know exactly how much is written, and
you can finish up the file when it's full and continue writing to a new
file.

That means of course that you have to write the XML header and root
element to the file yourself.
 
G

Göran Andersson

Manu said:
But a very interesting discussion was started by this topic.

Yes, moot discussons are always interresting, otherwise they would not
exist in the first place. :)
 
A

Anthony Jones

not_a_commie said:
I'm not sure you need to ditch the XmlDocument object. However, I
absolutely agree that a MemoryStream is almost never what you want
when dealing with XML. It will add byte markers to the start of the
stream. You should write out your documents this way:

using (var writer = new XmlTextWriter(filename, new UTF8Encoding
(false)))
{
writer.Formatting = Formatting.Indented;
xmlDoc.Save(writer);
writer.Close();
}

At what point would the OP know that the doc needed save and another
started?

We tend to stick with XmlDocument because we're comfortable with it and its
more flexiable than the forward only creation style needed when using an
XmlTextWriter directly. In many situations, though, the XmlTextWriter can
be used with no loss of functionality and its much more efficient. In this
special case it actual provides us with a function thats very difficult to
achieve with XmlDocument.
 
G

Göran Andersson

Anthony said:
A far better approach would be to ditch XmlDocument altogether.

Create XmlTextWriter on a BufferedStream on a FileStream.

Use XmlTextWriter to create the Xml as needed which will just stream out
the destination file, the BufferedStream Length property would tell you
exacly how much has been written to the file.

When appropriate the existing content can be closed off and a new pair
of streams and a writer could be created to continue with the next
traunch of content and so on.

This approach allows you to accurately monitor the size of XML file
being created, doesn't require frequent large strings to be generated
and dropped (as using OuterXml.Length would do) and limits the demand
for memory in the application (memory requirements limited to the size
of buffer choosen when creating the BufferedStream).

This would definitely be a much more memory efficient way, if it's
possible to avoid the XmlDocument in the first place.

However, it would be difficult to determine before writing the node if
it would make the file too big. You would probably just have to
determine the possible maximum size of a node, and move on to the next
file when a node possibly could make the file too large instead of when
it actually would be making the file too large.
 
A

Anthony Jones

Göran Andersson said:
This would definitely be a much more memory efficient way, if it's
possible to avoid the XmlDocument in the first place.

However, it would be difficult to determine before writing the node if it
would make the file too big. You would probably just have to determine the
possible maximum size of a node, and move on to the next file when a node
possibly could make the file too large instead of when it actually would
be making the file too large.


Yes I think you would need some such heuristics on it and you may be cutting
a file shorter than it needed to be as a result.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top