Solved

TList of records - memory use

Posted on 2004-08-31
13
531 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
  • 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
 
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
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

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

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
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…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

744 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now