Recent

Author Topic: Size of memory  (Read 5324 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8029
Re: Size of memory
« Reply #30 on: October 22, 2024, 09:05:49 am »
Your initial code is bad. You can't release that memory.

Yes, that I agree with: the original pointer has to be saved /precisely/, and that also applies when it might look as though it could be reduced to some more-efficient canonical form (I'm thinking of the original x86 here).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Okoba

  • Hero Member
  • *****
  • Posts: 555
Re: Size of memory
« Reply #31 on: October 22, 2024, 11:07:20 am »
@BrunoK, thank you for the note. So it seems memory amount returned from MemSize is safe to use.
Bu what are the Sys* methods?

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: Size of memory
« Reply #32 on: October 22, 2024, 11:19:32 am »
@okoba:
have a look at this source.
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Thaddy

  • Hero Member
  • *****
  • Posts: 16177
  • Censorship about opinions does not belong here.
Re: Size of memory
« Reply #33 on: October 22, 2024, 11:23:19 am »
That is simply wrong. You have the sources, look at them.
By now I have proved you wrong.
If I smell bad code it usually is bad code and that includes my own code.

BrunoK

  • Hero Member
  • *****
  • Posts: 623
  • Retired programmer
Re: Size of memory
« Reply #34 on: October 22, 2024, 01:00:03 pm »
@BrunoK, thank you for the note. So it seems memory amount returned from MemSize is safe to use.
Bu what are the Sys* methods?
Perequisite for this comment, concerns only heap.inc standard heap allocation.
The standard memory allocation methods are indirect and are addressed via the definition in
Code: Pascal  [Select][+][-]
  1. const
  2.   MemoryManager: TMemoryManager = (
  3.    ...
  4.     GetMem: @SysGetMem;
  5.    ...
When you do a GetMem, the compiler generates a call via the procedure specified in the constant record MemoryManager.
The default GetMem in Heap.inc,  @SysGetMem function, is compiled in the executable file and is immediately available at the start of the program.

When you ask for heap trace, very early in the initialization, heaptrc.pp will save and then replace the MemoryManager record with its own, it facades the original calls with its own implementation. HeapTrc will itself use the original copy of MemoryManager for effective memory allocation.

One should not have any expectation on eventual oversized memory availability, but can use the extra memory if any has been allocated. The following program, with/wihout heap.inc / heaptrc will not give the same values. A program compiled with cmem is likely to return the same values as HeapTrc.

Code: Pascal  [Select][+][-]
  1. program pgmGetMem;
  2.  
  3. // https://forum.lazarus.freepascal.org/index.php?action=post;quote=534601;topic=68982.30#postmodify
  4.  
  5.   function myGetMem(aSize: UIntPtr): pointer;
  6.   begin
  7.     Result := GetMem(aSize); // <- this is the GetMem
  8.     FillChar(Result^, MemSize(Result), $FF); // Initialize the available memory
  9.                                              // allocated for pointer Result
  10.   end;
  11.  
  12. var
  13.   vMemP0: Pointer;
  14.   vMemP1: Pointer;
  15.   vMemP24: Pointer;
  16.   vMemP25: Pointer;
  17. begin
  18.   {$IFDEF CPU32}
  19.   WriteLn('CPU32');
  20.   {$ENDIF}
  21.   {$IFDEF CPU64}
  22.   WriteLn('CPU64');
  23.   {$ENDIF}
  24.  
  25.   vMemP0 := myGetMem(0);
  26.   WriteLn('MemSize(vMemP0)=', MemSize(vMemP0));
  27.   vMemP1 := myGetMem(1);
  28.   WriteLn('MemSize(vMemP1)=', MemSize(vMemP1));
  29.   vMemP24 := myGetMem(24);
  30.   WriteLn('MemSize(vMemP24)=', MemSize(vMemP24));
  31.   vMemP25 := myGetMem(25);
  32.   WriteLn('MemSize(vMemP25)=', MemSize(vMemP25));
  33.  
  34.   readln;
  35.  
  36.   FreeMem(vMemP25);
  37.   FreeMem(vMemP24);
  38.   FreeMem(vMemP1);
  39.   FreeMem(vMemP0);
  40. end.

Fibonacci

  • Hero Member
  • *****
  • Posts: 604
  • Internal Error Hunter
Re: Size of memory
« Reply #35 on: October 22, 2024, 01:29:09 pm »
I have a question. What does FreeMem() return? The docs dont mention it.

I assumed it returns the memory size allocated to the pointer by GetMem(), but look at this:

Code: Pascal  [Select][+][-]
  1. var
  2.   p: pointer;
  3.   u: ptruint;
  4. begin
  5.   p := GetMem(500);
  6.   writeln('memsize = ', MemSize(p));
  7.   u := Freemem(p);
  8.   writeln('freemem = ', u);
  9.   readln;
  10. end.

Code: Pascal  [Select][+][-]
  1. memsize = 504
  2. freemem = 512

So, I request 500 bytes, the size is 504, and FreeMem() returns 512...

Okoba

  • Hero Member
  • *****
  • Posts: 555
Re: Size of memory
« Reply #36 on: October 22, 2024, 01:41:25 pm »
@BrunoK Thank you very much, very helpful.
@Fibonacci it seems the documentations need improvement in this section. I am too curious about what it returns, but I am guessing it is the real size of the memory, the allocated memory + the size of Size property.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8029
Re: Size of memory
« Reply #37 on: October 22, 2024, 01:52:50 pm »
You ask for 500 but it needs heap management overhead. You're allocated 512 and told you've got 504, which means that heap management occupies 8 bytes. Freemem() apparently tells you the amount freed including the 8 bytes of heap management overhead.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

BrunoK

  • Hero Member
  • *****
  • Posts: 623
  • Retired programmer
Re: Size of memory
« Reply #38 on: October 22, 2024, 02:06:44 pm »
I have a question. What does FreeMem() return? The docs dont mention it.
It returns the total size of the allocated (chunk) block of memory including the size info like :
Code: Pascal  [Select][+][-]
  1.   { Effectively used memory for aSize for small blocks }
  2.   function CalculatedChunkSize(aSize:UIntPtr):UIntPtr;
  3.   begin
  4.     Result := ((SizeOf(UIntPtr) + aSize + (Sizeof(UIntPtr) * 4) - 1)
  5.                div (Sizeof(UIntPtr) * 4)) *
  6.                (Sizeof(UIntPtr) * 4);
  7.   end;

VisualLab

  • Hero Member
  • *****
  • Posts: 573
Re: Size of memory
« Reply #39 on: October 22, 2024, 04:31:03 pm »
Tests for computer: Windows 10 64-bit, Lazarus: 3.4 (64 bit) - modified.

Test 1:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   {TForm1}
  12.   TForm1 = class(TForm)
  13.     Button1: TButton;
  14.     Memo1: TMemo;
  15.     procedure Button1Click(Sender: TObject);
  16.   end;
  17.  
  18. var
  19.   Form1: TForm1;
  20.  
  21. implementation
  22.  
  23. {$R *.lfm}
  24.  
  25. {TForm1}
  26.  
  27. procedure TForm1.Button1Click(Sender: TObject);
  28. var
  29.   LSizeOfRequestedMemory, LSizeOfReceivedMemory, LSizeOfReleasedMemory, LSizeOfPointer, LDifferenceOfSizes: Integer;
  30.   LPointerToReceivedMemory: Pointer;
  31. begin
  32.   LSizeOfRequestedMemory := 1024;
  33.   LPointerToReceivedMemory := GetMem(LSizeOfRequestedMemory);
  34.   LSizeOfReceivedMemory := MemSize(LPointerToReceivedMemory);
  35.   LSizeOfReleasedMemory := FreeMem(LPointerToReceivedMemory);
  36.   LSizeOfPointer := SizeOf(Pointer);
  37.   LDifferenceOfSizes := LSizeOfReceivedMemory - LSizeOfPointer;
  38.   Memo1.Lines.Add('Size of requested memory: ' + LSizeOfRequestedMemory.ToString);
  39.   Memo1.Lines.Add('Size of received memory: ' + LSizeOfReceivedMemory.ToString);
  40.   Memo1.Lines.Add('Size of released memory: ' + LSizeOfReleasedMemory.ToString);
  41.   Memo1.Lines.Add('Size of pointer: ' + LSizeOfPointer.ToString);
  42.   Memo1.Lines.Add('Difference of sizes (received - pointer): ' + LDifferenceOfSizes.ToString);
  43. end;
  44.  
  45. end.

Code as above, but memory allocation request equal to 500. Results of the operation in screenshots.
« Last Edit: October 22, 2024, 04:38:35 pm by VisualLab »

jamie

  • Hero Member
  • *****
  • Posts: 6735
Re: Size of memory
« Reply #40 on: October 23, 2024, 12:39:26 am »
I can picture passing a pointer as a parameter to a function and then that function decides to use MemSize to see how big the storage is in conjunction with other code.

 I See a mess!  I also see and hear dead people!  :o
The only true wisdom is knowing you know nothing

LV

  • Full Member
  • ***
  • Posts: 153
Re: Size of memory
« Reply #41 on: October 23, 2024, 03:11:04 pm »
There is some pattern in memory allocation (Windows 11, FPC 3.2.2).  ;)

Code: Pascal  [Select][+][-]
  1. Program Example;
  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 12 do
  21.   begin
  22.     MM := i * 8;
  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.  

MM = 8   MemSize(P) = 24
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 16
FreeMem(P) = 32   CalculatedChunkSize(MM) = 32
MM = 16   MemSize(P) = 24
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 16
FreeMem(P) = 32   CalculatedChunkSize(MM) = 32
MM = 24   MemSize(P) = 24
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 16
FreeMem(P) = 32   CalculatedChunkSize(MM) = 32
MM = 32   MemSize(P) = 56
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 48
FreeMem(P) = 64   CalculatedChunkSize(MM) = 64
MM = 40   MemSize(P) = 56
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 48
FreeMem(P) = 64   CalculatedChunkSize(MM) = 64
MM = 48   MemSize(P) = 56
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 48
FreeMem(P) = 64   CalculatedChunkSize(MM) = 64
MM = 56   MemSize(P) = 56
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 48
FreeMem(P) = 64   CalculatedChunkSize(MM) = 64
MM = 64   MemSize(P) = 88
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 80
FreeMem(P) = 96   CalculatedChunkSize(MM) = 96
MM = 72   MemSize(P) = 88
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 80
FreeMem(P) = 96   CalculatedChunkSize(MM) = 96
MM = 80   MemSize(P) = 88
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 80
FreeMem(P) = 96   CalculatedChunkSize(MM) = 96
MM = 88   MemSize(P) = 88
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 80
FreeMem(P) = 96   CalculatedChunkSize(MM) = 96
MM = 96   MemSize(P) = 120
SizeOf(Pointer) = 8   MemSize(P)-SizeOf(Pointer) = 112
FreeMem(P) = 128   CalculatedChunkSize(MM) = 128
 :o


tetrastes

  • Hero Member
  • *****
  • Posts: 594
Re: Size of memory
« Reply #42 on: October 23, 2024, 03:41:11 pm »
Summary, as I understand it.
GetMem(N) allocates memory M>= N, which can be known by MemSize and used, + some memory S for size, which is 8 or 24 for larger N (and may be greater?).
The whole allocated memory M+S can be calculated by CalculatedChunkSize(N) and is freed by FreeMem. 
There is no sense in MemSize(P)-SizeOf(Pointer).

LV

  • Full Member
  • ***
  • Posts: 153
Re: Size of memory
« Reply #43 on: October 23, 2024, 04:57:20 pm »
So, for my Win64 the formula determines memory allocation by GetMem(N): ((N div 32) + 1) * 32.

Thaddy

  • Hero Member
  • *****
  • Posts: 16177
  • Censorship about opinions does not belong here.
Re: Size of memory
« Reply #44 on: October 23, 2024, 05:41:50 pm »
That is close or equal to what the default manager does. (bucket size)
Thank you for mentioning and using Freemem, that will solve Jamie's problem if he finally gets it. >:D
If I smell bad code it usually is bad code and that includes my own code.

 

TinyPortal © 2005-2018