Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2010-02

GetHeapStatus.TotalAllocated

25 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Nikolai Zhubr

Hello people,

after switching to FPC 2.4.0 I've noticed that:

1) GetHeapStatus.TotalAllocated does not seem to reflect size of allocations made by other threads anymore (I can provide a small example). I think such behaviour is not quite correct.

2) GetHeapStatus.TotalAllocated sometimes return negative values, though I haven't been able to prepare a reasonably small example yet (should I?)

Thank you!

Nikolai

Reply by email

Vincent Snijders
to Nikolai Zhubr
Nikolai Zhubr wrote 5 lines
Hello people, 2) GetHeapStatus.TotalAllocated sometimes return negative values, though I haven't been able to prepare a reasonably small example yet (should I?)

Maybe that is caused by an overflow. So you need a long running example.

Vincent

Reply by email

Nikolai Zhubr
to Vincent Snijders

13.02.2010 14:50, Vincent Snijders:

Show quoted text 6 lines
> 2) GetHeapStatus.TotalAllocated sometimes return negative values, > though I haven't been able to prepare a reasonably small example yet > (should I?) > Maybe that is caused by an overflow. So you need a long running example.

The program in question does not consume much memory and was running a few hours. It is multithreaded. According to task manager (this was on windows) actual mem usage was approximately the same as before (below 10 Mbytes).

Nikolai

Show quoted text 6 lines
Vincent _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Marco van de Voort
to Nikolai Zhubr: after switching to FPC 2.4.0 I've noticed that: 1) GetHeapStatus.TotalAllocated does not…

In our previous episode, Nikolai Zhubr said:

Show quoted text 5 lines
after switching to FPC 2.4.0 I've noticed that: 1) GetHeapStatus.TotalAllocated does not seem to reflect size of allocations made by other threads anymore (I can provide a small example). I think such behaviour is not quite correct.

Afaik that is a feature? 2.4.0 sports a threaded memorymanagers where threads can allocate memory without accessing global locks (and thus statistics)

Note that that doesn't mean it is ok, but it might not be fixable 100%

2) GetHeapStatus.TotalAllocated sometimes return negative values, though I haven't been able to prepare a reasonably small example yet (should I?)

Please attach example programs to a bugreport. Thank you.

Reply by email

Jonas Maebe
to Nikolai Zhubr: after switching to FPC 2.4.0 I've noticed that: 1) GetHeapStatus.TotalAllocated does not…
Nikolai Zhubr wrote
1) GetHeapStatus.TotalAllocated does not seem to reflect size of allocations made by other threads anymore (I can provide a small example). I think such behaviour is not quite correct.

The heap manager is now separate per thread so it offers much better performance. Keeping track of this information aggregated for all threads would slow things down again (even if it would be done using atomic operations).

2) GetHeapStatus.TotalAllocated sometimes return negative values, though I haven't been able to prepare a reasonably small example yet (should I?)

Yes.

Jonas

Reply by email

Nikolai Zhubr
to Jonas Maebe

13.02.2010 16:33, Jonas Maebe:

The heap manager is now separate per thread so it offers much better performance. Keeping track of this information aggregated for all threads would slow things down again (even if it would be done using atomic operations).

So it is indeed not possible to obtain global status anymore? But how would one check global heap usage then? The necessity to collect such information by iterating through all threads somehow scares me... In particular, if some thread happens to hang or dies unexpectedly. Still, is there some recommended way to estimate heap usage per application, at least approximately?

> 2) GetHeapStatus.TotalAllocated sometimes return negative values, though I haven't been able to prepare a reasonably small example yet (should I?) Yes.

Ok, I'll try to figure.

Thank you!

Nikolai

Reply by email

Jonas Maebe
to Nikolai Zhubr
Nikolai Zhubr wrote
13.02.2010 16:33, Jonas Maebe: > The heap manager is now separate per thread so it offers much better performance. Keeping track of this information aggregated for all threads would slow things down again (even if it would be done using atomic operations). So it is indeed not possible to obtain global status anymore?

Not with the default heap manager.

But how would one check global heap usage then? The necessity to collect such information by iterating through all threads somehow scares me... In particular, if some thread happens to hang or dies unexpectedly. Still, is there some recommended way to estimate heap usage per application, at least approximately?

Not without implementing a custom memory manager that does this or using some OS function to obtain this information.

Jonas

Reply by email

Nikolai Zhubr
to Jonas Maebe

13.02.2010 22:51, Jonas Maebe:
[trim]

Not without implementing a custom memory manager that does this or using some OS function to obtain this information.

So even some extra InterlockedExchangeAdd would be too expensive?

Reply by email

Jonas Maebe
to Nikolai Zhubr
Nikolai Zhubr wrote
13.02.2010 22:51, Jonas Maebe: [trim] > Not without implementing a custom memory manager that does this or using some OS function to obtain this information. So even some extra InterlockedExchangeAdd would be too expensive?

It would make the memory manager slower, and I don't think that aggregating few statistics is a good reason to do so (especially since very few programs actually use that data). If you want that data, you can always install a very simple memory manager that simply calls through to the original one, but which keeps track of global statistics.

Jonas

Reply by email

Jonas Maebe
to Nikolai Zhubr
Nikolai Zhubr wrote
13.02.2010 16:33, Jonas Maebe: [...] > The heap manager is now separate per thread so it offers much better performance. Wait a minute. Is it then still legal for any thread to dispose heap blocks allocated by another thread?

Yes, that's taken care of behind the scenes.

Jonas

Reply by email

Nikolai Zhubr
to Jonas Maebe

14.02.2010 0:30, Jonas Maebe:

>> The heap manager is now separate per thread so it offers much better performance. > Wait a minute. Is it then still legal for any thread to dispose heap blocks allocated by another thread? Yes, that's taken care of behind the scenes.

Ok. That is good.
Now, I'm starting to suspect that negative TotalAllocated values just result from doing deallocations in a different thread, which is what my programm actually does all the time. I'll go to make a small test.

Nikolai

Show quoted text 6 lines
Jonas_______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Nikolai Zhubr
to Jonas Maebe: The heap manager is now separate per thread so it offers much better performance. Keeping…

13.02.2010 16:33, Jonas Maebe:

> 2) GetHeapStatus.TotalAllocated sometimes return negative values, though I haven't been able to prepare a reasonably small example yet (should I?) Yes.

I haven't yet succeeded in reproducing negative values in a small example, however I think the program below demonstrates some misbehaviour already, because after deallocation, TotalAllocated stays as before deallocation. The output is:
In program: 0 M
In thread: 2 M
In thread: 2 M
Deallocated! <<<=== After this, TotalAllocated should go down somewhere? In program: 0 M
In thread: 2 M <<<=== ... but it doesn't!
In program: 0 M
In thread: 2 M

--------------------------------------------------------
program heapstatustest;
{$mode delphi}
{$apptype console}
uses
   SysUtils, Classes;
type
   TMyThread = class(TThread)
     procedure Execute; override;
   end;
procedure ShowAllocatedSize(s: string);
begin
   writeln(s + IntToStr(GetHeapStatus.TotalAllocated shr 20) + ' M');
end;
var
   p: pointer = nil;
procedure TMyThread.Execute;
begin
   GetMem(p, 1024*1024*2);
   repeat
     ShowAllocatedSize('In thread: ');
     sleep(1000);
   until false;
end;
begin
   TMyThread.create(false);
   repeat
     if p  nil then
     begin
       FreeMem(p, 1024*1024*2);
       p := nil;
       writeln('Deallocated!');
     end;
     ShowAllocatedSize('In program: ');
     sleep(1000);
   until false;
end.

Reply by email

Nikolai Zhubr
to Seth Grover

14.02.2010 6:04, Seth Grover:

As for the negative numbers (possible overflow) from the heap status, I logged a bug on that, with an example program, quite some time ago. http://bugs.freepascal.org/view.php?id=14315

Ah, so negative numbers are in bugtracker already, ok.

But still I think the issue with threads is maybe different because it happens immediately at the very first allocation+deallocation. I'll fill a separate bugreport.

Thank you!

Nikolai

Show quoted text 13 lines
-SG -- This email is fiction. Any resemblance to actual events or persons living or dead is purely coincidental. Seth Grover sethdgrover[at]gmail[dot]com _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Nikolai Zhubr
to Michael Schnell

16.02.2010 14:39, Michael Schnell:

Show quoted text 6 lines
On 02/13/2010 09:38 PM, Jonas Maebe wrote: > It would make the memory manager slower, and I don't think that aggregating few statistics is a good reason to do so > Yep. But it should be possible to implement a function that on request (slowly) collects the list of (or at last sum of) the state of all existing threads.

Exactly! That's what I'd be happy with. I'll call it once per second so a bit of slowdown wouldn't matter much. I think creating a custom "wrapper" heap manager just to be able to get total mem usage is a bit overkill, though maybe I'll try that method too.

Nikolai

Show quoted text 6 lines
-Michael _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Jonas Maebe
to Nikolai Zhubr
Nikolai Zhubr wrote 9 lines
16.02.2010 14:39, Michael Schnell: > On 02/13/2010 09:38 PM, Jonas Maebe wrote: >> It would make the memory manager slower, and I don't think that >> aggregating few statistics is a good reason to do so >> > Yep. But it should be possible to implement a function that on > request > (slowly) collects the list of (or at last sum of) the state of all > existing threads.

That would require separately maintaining a list of the memory managers of all threads, which afaik does not exist currently.

Exactly! That's what I'd be happy with. I'll call it once per second so a bit of slowdown wouldn't matter much. I think creating a custom "wrapper" heap manager just to be able to get total mem usage is a bit overkill, though maybe I'll try that method too.

I think it is the only proper way.

Jonas

Reply by email

Nikolai Zhubr
to Jonas Maebe

16.02.2010 18:59, Jonas Maebe:
[...]

Show quoted text 9 lines
That would require separately maintaining a list of the memory managers of all threads, which afaik does not exist currently. > Exactly! That's what I'd be happy with. I'll call it once per second > so a bit of slowdown wouldn't matter much. I think creating a custom > "wrapper" heap manager just to be able to get total mem usage is a bit > overkill, though maybe I'll try that method too. I think it is the only proper way.

Ok. Would it be sufficient to only hook Getmem and Freemem?

From a brief look it seems other members (such as ReAllocMem) do not modify the heap directly, so they need not be hooked I guess.

Nikolai

Show quoted text 7 lines
Jonas _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Nikolai Zhubr
to Nikolai Zhubr

16.02.2010 20:17, Nikolai Zhubr:

Ok. Would it be sufficient to only hook Getmem and Freemem? From a brief look it seems other members (such as ReAllocMem) do not modify the heap directly, so they need not be hooked I guess.

After some more reading and testing I think generally GetMem, FreeMem, and FreeMemSize should be enough, however I'm not sure about some corner cases. (For example, allocating zero bytes is valid, but such allocation will result in non-zero memory block, so this needs a special check probably.) So overall, this is not absolutely trivial.

Nikolai

Show quoted text 15 lines
Nikolai > > > Jonas > _______________________________________________ > fpc-devel maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-devel > _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Nikolai Zhubr
to Marco van de Voort: In our previous episode, Nikolai Zhubr said: Afaik that is a feature? 2.4.0 sports a…

13.02.2010 15:32, Marco van de Voort:

> 2) GetHeapStatus.TotalAllocated sometimes return negative values, though > I haven't been able to prepare a reasonably small example yet (should I?) Please attach example programs to a bugreport. Thank you.

I've created a small self-consistent example, but something is wierd with it. In order to reproduce the effect, put the example in a file named 000.pas (with other filename misbehaviour might not trigger!), compile with 2.4.0 (do not add any options to compiler) and run on windows. Then (hopefully) you will see bogus TotalAllocated values: 4194281K <enter>
4194257K <enter>
4194233K <...>
4194208K
4194184K
4194160K
4194136K
4194112K
4194088K
4194064K
....
Please note that while the problem itself is quite stable, the example is not. That is, if you insert or remove some code, change the filename etc, then the example might just start work properly! (Maybe it is alignment-related, not sure)

I haven't sent this to mantis yet. Please someone let me know if this example is appropriate (or not).

Thank you.

Nikolai
------------------------- cut -------------------------------
{$mode delphi}
{$apptype console}
uses
   SysUtils;
const
   data: array [0.. 12] of integer = (9000, 1000, 9000, 12, 9000, 26,
9000, 74, 9000, 1, 2000, 9000, 1);
var
   p: pointer;
   i: integer;
begin
   p := nil;
   repeat
     for i := low(data) to high(data) do
       ReAllocMem(p, data[i]*4);
     writeln((GetHeapStatus.TotalAllocated shr 10), 'K');
     readln;
   until false;
end.
------------------------- cut -------------------------------

Reply by email

Marco van de Voort
to Nikolai Zhubr

In our previous episode, Nikolai Zhubr said:

Show quoted text 7 lines
Please note that while the problem itself is quite stable, the example is not. That is, if you insert or remove some code, change the filename etc, then the example might just start work properly! (Maybe it is alignment-related, not sure) I haven't sent this to mantis yet. Please someone let me know if this example is appropriate (or not).

I think so, please enter it in Mantis.

I quickly looked around and noticed two things:

1)
It is also striking that it seems to happen on the first realloc of a NIL ptr, maybe that is a scenario not properly updated, sizewise.

2)
I also see a "exit(true)" in systryresize that doesn't update sizes.

Reply by email

Nikolai Zhubr
to Marco van de Voort

18.02.2010 0:29, Marco van de Voort:

I think so, please enter it in Mantis.

Ok, should I create a new entry or rather add it to bug 0014315 (http://bugs.freepascal.org/view.php?id=14315) which is probably the same issue, though filled for earlier version?

Show quoted text 14 lines
I quickly looked around and noticed two things: 1) It is also striking that it seems to happen on the first realloc of a NIL ptr, maybe that is a scenario not properly updated, sizewise. 2) I also see a "exit(true)" in systryresize that doesn't update sizes. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Nikolai Zhubr
to Marco van de Voort: In our previous episode, Nikolai Zhubr said: I think so, please enter it in Mantis. I…

18.02.2010 0:29, Marco van de Voort:

> I haven't sent this to mantis yet. Please someone let me know if this > example is appropriate (or not). I think so, please enter it in Mantis.

I've created yet another (alternative) example for the same matter and filed a new bugreport including both.

http://bugs.freepascal.org/view.php?id=15805

Nikolai

Reply by email