[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

TList of records - memory use

Posted on 2004-08-31
13
Medium Priority
?
546 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 1000 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 27

Assisted Solution

by:kretzschmar
kretzschmar earned 1000 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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Suggested Courses

656 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