Recent

Author Topic: Size of memory  (Read 6306 times)

Okoba

  • Hero Member
  • *****
  • Posts: 573
Re: Size of memory
« Reply #45 on: October 23, 2024, 05:45:04 pm »
Here is an issue about this topic: https://gitlab.com/freepascal.org/fpc/documentation/-/issues/39403
I hope someone with sufficient official information improve them.

BrunoK

  • Hero Member
  • *****
  • Posts: 647
  • Retired programmer
Re: Size of memory
« Reply #46 on: October 23, 2024, 06:14:37 pm »
So, for my Win64 the formula determines memory allocation by GetMem(N): ((N div 32) + 1) * 32.
Generalized for heap.inc CPU32 / CPU64 and small blocks.
Minimum likely memory used for allocation : GetMem(N): ((N div SizeOf(UIntPtr) * 4 + 1) * SizeOf(UIntPtr)*4. I write "likely" because the memory allocator might return a freed block of a larger size.

In fact it is of no interest to us programmers to know that since we want N bytes.
Some routines in the rtl make good use of it, avoiding excessive calls to GetMem / FreeMem that could be avoided.

Why did I get  interested in the subject ? Because when using cmem, MemSize returns exactly what was requested and I thought it was unfair regarding program speed. But actually my benchmarks regarding changing size of allocation (modifed FPC) to put cmem on par with heap.inc did not indicate a noticeable difference.

LV

  • Full Member
  • ***
  • Posts: 197
Re: Size of memory
« Reply #47 on: October 23, 2024, 06:32:13 pm »
Thank you for the clarification. I'm not a programmer. This is a hobby of mine. :)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12004
  • FPC developer.
Re: Size of memory
« Reply #48 on: October 24, 2024, 11:22:32 am »
Why did I get  interested in the subject ? Because when using cmem, MemSize returns exactly what was requested

(but that might be because cmem can't look inside the libc allocator. It can only works through its abstraction)

LV

  • Full Member
  • ***
  • Posts: 197
Re: Size of memory
« Reply #49 on: October 24, 2024, 08:25:13 pm »
Looking at Reply #41, a simple observation suggests
FreeMem(GetMem(N)) = MemSize(GetMem(N)) + SizeOf(Pointer) =  ((N div 32) + 1) * 32.
This works on both Windows and Linux (tested).

Here is an issue about this topic: https://gitlab.com/freepascal.org/fpc/documentation/-/issues/39403
I hope someone with sufficient official information improve them.

Diving into the content of heap.inc can be quite tedious for a simple user of FPC and Lazarus, so this suggestion is helpful.

Updated: However, If we take a closer look at the contents of heap.inc, "the memory allocator might return a freed block of a larger size".
« Last Edit: October 24, 2024, 09:27:11 pm by LV »

tetrastes

  • Hero Member
  • *****
  • Posts: 622
Re: Size of memory
« Reply #50 on: October 24, 2024, 09:42:55 pm »
Looking at Reply #41, a simple observation suggests
FreeMem(GetMem(N)) = MemSize(GetMem(N)) + SizeOf(Pointer) =  ((N div 32) + 1) * 32.
This works on both Windows and Linux (tested).

Tested?
64 bit:
MemSize(GetMem(1024)) = 1032
FreeMem(GetMem(1024)) = 1056 = CalculatedChunkSize(1024)  = (1024 div 32 + 1) * 32
1056 - 1032 = 24

32 bit:
MemSize(GetMem(1024)) = 1028
FreeMem(GetMem(1024)) = 1040 = CalculatedChunkSize(1024) = (1024 div 16 + 1) * 16
1040 - 1028 = 12
« Last Edit: October 24, 2024, 09:52:48 pm by tetrastes »

LV

  • Full Member
  • ***
  • Posts: 197
Re: Size of memory
« Reply #51 on: October 24, 2024, 09:55:39 pm »

small blocks.



Updated: However, If we take a closer look at the contents of heap.inc, "the memory allocator might return a freed block of a larger size".


Code: Pascal  [Select][+][-]
  1. MM = 128   MemSize(P) = 152
  2. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 144
  3. FreeMem(P) = 160   CalculatedChunkSize(MM) = 160
  4. MM = 256   MemSize(P) = 280
  5. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 272
  6. FreeMem(P) = 288   CalculatedChunkSize(MM) = 288
  7. MM = 384   MemSize(P) = 408
  8. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 400
  9. FreeMem(P) = 416   CalculatedChunkSize(MM) = 416
  10. MM = 512   MemSize(P) = 536
  11. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 528
  12. FreeMem(P) = 544   CalculatedChunkSize(MM) = 544
  13. ------------------------------------------------------
  14. MM = 640   MemSize(P) = 648
  15. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 640
  16. FreeMem(P) = 672   CalculatedChunkSize(MM) = 672
  17. MM = 768   MemSize(P) = 776
  18. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 768
  19. FreeMem(P) = 800   CalculatedChunkSize(MM) = 800
  20. MM = 896   MemSize(P) = 904
  21. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 896
  22. FreeMem(P) = 928   CalculatedChunkSize(MM) = 928
  23. MM = 1024   MemSize(P) = 1032
  24. SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 1024
  25. FreeMem(P) = 1056   CalculatedChunkSize(MM) = 1056
  26.  
« Last Edit: October 24, 2024, 10:02:44 pm by LV »

tetrastes

  • Hero Member
  • *****
  • Posts: 622
Re: Size of memory
« Reply #52 on: October 24, 2024, 10:09:15 pm »

small blocks.



Yes, of course. Do you think 1024 bytes is large block?
But this is wrong:

FreeMem(GetMem(N)) = MemSize(GetMem(N)) + SizeOf(Pointer)


LV

  • Full Member
  • ***
  • Posts: 197
Re: Size of memory
« Reply #53 on: October 24, 2024, 10:25:29 pm »
It's not me who thinks so. Argue with heap.inc.

tetrastes

  • Hero Member
  • *****
  • Posts: 622
Re: Size of memory
« Reply #54 on: October 24, 2024, 10:33:54 pm »
Once more:
64 bit:
MemSize(GetMem(1024)) = 1032
FreeMem(GetMem(1024)) = 1056 = CalculatedChunkSize(1024)  = (1024 div 32 + 1) * 32
1056 - 1032 = 24 <> SizeOf(Pointer)

And this is in accordance with heap.inc.


LV

  • Full Member
  • ***
  • Posts: 197
Re: Size of memory
« Reply #55 on: October 24, 2024, 10:42:25 pm »
See results above

small block
MM = 512   MemSize(P) = 536
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 528
FreeMem(P) = 544   CalculatedChunkSize(MM) = 544
-----------------------------------------------------
large block
MM = 640   MemSize(P) = 648
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 640
FreeMem(P) = 672   CalculatedChunkSize(MM) = 672

LV

  • Full Member
  • ***
  • Posts: 197
Re: Size of memory
« Reply #56 on: October 24, 2024, 10:55:51 pm »
Ok, run the Win64 program

Code: Pascal  [Select][+][-]
  1. Program project1;
  2.  
  3. { Program to demonstrate the FreeMem and GetMem functions. }
  4.  
  5. Var
  6.  P : Pointer;
  7.  MM : Longint;
  8.  F: PtrUInt;
  9.  i: Integer;
  10.  
  11.  { Effectively used memory for aSize for small blocks. From BrunoK }
  12. function CalculatedChunkSize(aSize:UIntPtr):UIntPtr;
  13. begin
  14.   Result := ((SizeOf(UIntPtr) + aSize + (Sizeof(UIntPtr) * 4) - 1)
  15.               div (Sizeof(UIntPtr) * 4)) *
  16.               (Sizeof(UIntPtr) * 4);
  17. end;
  18.  
  19. begin
  20.   for i := 1 to 8 do
  21.   begin
  22.     MM := i * 64;
  23.     write('MM = ', MM);
  24.     P := GetMem(MM);
  25.     writeln('   MemSize(P) = ', MemSize(P));
  26.     write('SizeOf(Pointer) = ', SizeOf(Pointer));
  27.     // From Jamie
  28.     writeln('   MemSize(P)-SizeOf(Pointer) = ', MemSize(P) - SizeOf(Pointer));
  29.     F := FreeMem(P);
  30.     write('FreeMem(P) = ', F);
  31.     // From BrunoK
  32.     writeln('   CalculatedChunkSize(MM) = ', CalculatedChunkSize(MM));
  33.   end;
  34.   readln;
  35. end.  
  36.  

and show the error.

tetrastes

  • Hero Member
  • *****
  • Posts: 622
Re: Size of memory
« Reply #57 on: October 25, 2024, 12:13:13 am »
I don't understand, what error?

But at last I have understood, what do you call "small" and "large" blocks. As "small" are those that <= 536 bytes
Code: Pascal  [Select][+][-]
  1. if size <= (maxblocksize - sizeof(tmemchunk_fixed_hdr)) then

and "large" are all others, the following equation is more general:
FreeMem(GetMem(N)) = MemSize(GetMem(N)) + 24  :D

LV

  • Full Member
  • ***
  • Posts: 197
Re: Size of memory
« Reply #58 on: October 25, 2024, 11:01:32 am »
It appears that everything is much easier (FPC 3.2.2 win64).
Code: Pascal  [Select][+][-]
  1. Program project1;
  2.  
  3. { Program to demonstrate the FreeMem and GetMem functions. }
  4.  
  5. Var
  6.  P : Pointer;
  7.  MGet, MGetSize, MAloc : Longint;
  8.  F: PtrUInt;
  9.  i: Integer;
  10.  
  11. begin
  12.   for i := 0 to 5 do
  13.   begin
  14.     MGet := i + 534;
  15.     P := GetMem(MGet);
  16.     MGetSize := MemSize(P) + SizeOf(Pointer);
  17.  
  18.     write('MGet = ', MGet);
  19.     write('   MGetSize = ', MGetSize);
  20.  
  21.     F := FreeMem(P);
  22.     write('   FreeMem = ', F);
  23.     writeln('   diff = ', F - MGetSize);
  24.   end;
  25.  
  26.   writeln('----------------------------------------------------------------');
  27.  
  28.   for i := 0 to 5 do
  29.   begin
  30.     MGet := i + 534;
  31.     P := GetMem(MGet);
  32.     MGetSize := MemSize(P) + SizeOf(Pointer);
  33.  
  34.     write('MGet = ', MGet);
  35.     write('   MGetSize = ', MGetSize);
  36.  
  37.     F := FreeMem(P);
  38.     if MGet <= 536 then
  39.       MAloc := MGetSize
  40.     else
  41.       MAloc := MGetSize + 16;
  42.     write('   FreeMem = ', F);
  43.     writeln('   diff = ', F - MAloc);
  44.   end;
  45.   readln;
  46. end.      
  47.  

Code: Text  [Select][+][-]
  1. MGet = 534   MGetSize = 544   FreeMem = 544   diff = 0
  2. MGet = 535   MGetSize = 544   FreeMem = 544   diff = 0
  3. MGet = 536   MGetSize = 544   FreeMem = 544   diff = 0
  4. MGet = 537   MGetSize = 560   FreeMem = 576   diff = 16
  5. MGet = 538   MGetSize = 560   FreeMem = 576   diff = 16
  6. MGet = 539   MGetSize = 560   FreeMem = 576   diff = 16
  7. ----------------------------------------------------------------
  8. MGet = 534   MGetSize = 544   FreeMem = 544   diff = 0
  9. MGet = 535   MGetSize = 544   FreeMem = 544   diff = 0
  10. MGet = 536   MGetSize = 544   FreeMem = 544   diff = 0
  11. MGet = 537   MGetSize = 560   FreeMem = 576   diff = 0
  12. MGet = 538   MGetSize = 560   FreeMem = 576   diff = 0
  13. MGet = 539   MGetSize = 560   FreeMem = 576   diff = 0
  14.  
So, the equation is more general:
FreeMem(GetMem(N)) =
  if N ≦ 536 then MemSize(GetMem(N)) + SizeOf(Pointer);
  else MemSize(GetMem(N)) + SizeOf(Pointer) + 16; :D
« Last Edit: October 25, 2024, 01:05:52 pm by LV »

tetrastes

  • Hero Member
  • *****
  • Posts: 622
Re: Size of memory
« Reply #59 on: October 25, 2024, 02:00:59 pm »
FreeMem(GetMem(N)) =
  if N ≦ 512 + SizeOf(Pointer)*3  then MemSize(GetMem(N)) + SizeOf(Pointer);
  else MemSize(GetMem(N)) + SizeOf(Pointer)*3

Then it works for 32 bit too  :D

 

TinyPortal © 2005-2018