Solved

TList of records - memory use

Posted on 2004-08-31
13
542 Views
Last Modified: 2008-02-01
Ok, this one most likely will not have an answer in code but i thought i would ask anyway - got to learn somehow and the books i have don't mention anything of use.

Question:  If i have a TList that is used to hold records, is there a way to find out the total memory in bytes used by all of the records in the TList?

0
Comment
Question by:foxjax
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 3
  • 2
13 Comments
 
LVL 4

Accepted Solution

by:
Evarest earned 250 total points
ID: 11940477
Actually this is a more difficult question than you imagine...

The problem lays with the record themselves. In my experience, they're being handled quite oddly (however this odd behaviour is entirely logic in the end). For example:

TMyRec = record
  Name: string;
  Item: integer;
  Period: string;
end;

As this record contains strings which can have different lengths, the memoryallocation will be different if you declare it like follows:

TMyRec = record
  Item: integer;
  Name: string;
  Period: string;
end;

The problem is that Delphi needs to be able to allocate enough memory to place enough reference data to each item in the record. The Integer will be placed in the record's place of the memory, the string will be referenced. This means that the actual string can reside in a different address of your memory, with only a pointer in the record's space.

All this I didn't perceive from some fancy book. It's only hands-on experience, as I once needed to allocate the memory myself.

IMPORTANT: in the latter text, i referred to space in memory as the actual space taken by the entire record. NOT the reference alone, which can easily be examined by calling SizeOf(TMyRec);

When you have the following record:

TMyRec = record
  Item: byte;
  Name: string[250];
  Period: string[250];
end;

This record is much easier to examine: just call sizeof(TMyRec) to get as answer 503 bytes. I might be that you notice that byte = 1 byte and 250*2=500 bytes. Thus normally the size would be 501 bytes. The reason is that the shortstrings always contain x+1 bytes where x: string[x]. These are null-terminated strings.

Conclusion:
You can esily derive the memoryspace of a record by using sizeof(TRecord). However take care if the record contains unterminated strings!

Hope to help,
Evarest
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 11940485
not so easy to calculate

in simple

each entry in the list = 4 bytes
plus the size of your record
plus the tlist-size itself

but if you have strings in your record,
then it will be become complicated, because
each same string is only once in memory
associated with a reference counter

meikl ;-)
0
 

Author Comment

by:foxjax
ID: 11940571
Evarest:  What if i changed the record structure to something like:

TMyRec = record
 Item: integer;                                      <== why the change to "byte" above?
 Name: array [0..4095] of char;
 Period: array [0..1023] of char;
end;

Would that make it easier?

meikl :

I see what you mean by "same string is only once in memory" - i assume delphi just puts a pointer into the place of the string since it already has the string in memory.  Sheesh, makes things a lot more complicated on the poor old developer.
0
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!

 
LVL 27

Assisted Solution

by:kretzschmar
kretzschmar earned 250 total points
ID: 11940626
TMyRec = record
 Item: integer;                            //4 Bytes          
 Name: array [0..4095] of char;    //4096 Bytes
 Period: array [0..1023] of char;   //1024 Bytes
end;

should be 5124 bytes total (calculated by head), if no alignment is issued

>i assume delphi just puts a pointer into the place
yep, but only if the definiton is unlimited (not by string[100])

meikl ;-)

0
 
LVL 4

Expert Comment

by:Evarest
ID: 11940705
>i assume delphi just puts a pointer into the place
yep, but only if the definiton is unlimited (not by string[100])

of course, as if you're using a null-terminated string, Delphi doesn't have need of placing it's contents somewhere else in the memory.
array [0..4095] of char will also place everything on the same place, but doesn't need a #0 terminate.


TMyRec = record
 Item: integer;                                      <== why the change to "byte" above?
 Name: array [0..4095] of char;
 Period: array [0..1023] of char;
end;

I had no reason to change it to byte, but just to give a different example.

[QUOTE]
I see what you mean by "same string is only once in memory" - i assume delphi just puts a pointer into the place of the string since it already has the string in memory.  Sheesh, makes things a lot more complicated on the poor old developer.
[/QUOTE]

This sheds light on the fact that you will have to take care that you free your memory correctly! Just calling

var
 MyRec: ^TMyRec;
begin
 dispose(MyRec);

with MyRec thus a Pointer, will NOT free all memory if the record contains strings.

Finalize(PMyRec(MyRec)^);

thus a record as parameter will free the memory. See my example in your other post for more info...

Evarest
0
 

Author Comment

by:foxjax
ID: 11940707
So with defining limits by using array [0..4095] of char, etc i can then get a good approximation of the total memory used by the records?
0
 

Author Comment

by:foxjax
ID: 11940818
seems sizeof always returns 4 for me - guess i am getting the size of the 4 byte pointer instead of the record in the TList
0
 

Author Comment

by:foxjax
ID: 11940881
oops - my mistake - got it now.
0
 

Author Comment

by:foxjax
ID: 11940946
One final point before i close this question:

I assume that to get a realistic approximation of memory used it would be

sizeof(<record>) * <number of records>) + SizeOf(<TList>)* <number of records>
0
 
LVL 4

Expert Comment

by:Evarest
ID: 11941111
"So with defining limits by using array [0..4095] of char, etc i can then get a good approximation of the total memory used by the records?"

Yep

"sizeof(<record>) * <number of records>) + SizeOf(<TList>)* <number of records>"
sizeof(<record>) * <number of records> + SizeOf(<TList>)

is better i guess, i'm not entirely sure though, never done that. It's only logic as you have a TList (thus the definition in the memory) and a lot of record behind eachother (which gives sizeof(<record>) * <number of records>)...

Greetings,
Evarest
0
 

Author Comment

by:foxjax
ID: 11941178
the reason i did SizeOf(<TList>)* <number of records> is that SizeOf(<TList>) always returns 4 (??) and since i realized that the TList is full of 4 byte pointers to records,  i added *<number of records> to allow for the memory used by the 4 bytes per record in the TList.

Make sense?

0
 

Author Comment

by:foxjax
ID: 11941197
I am going to split the points between the both of you - i raised them to 500 so i can give the original 250 to each of you.  I hope you both agree that it is fair.
0
 

Author Comment

by:foxjax
ID: 11941773
Thanks again guys - i found that quiet informative
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…

691 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