16

I found an article on About.com that tells you how you can manage your apps memory.

Here is the code:

procedure TrimAppMemorySize;
var
  MainHandle : THandle;
begin
  try
    MainHandle := OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessID) ;
    SetProcessWorkingSetSize(MainHandle, $FFFFFFFF, $FFFFFFFF) ;
    CloseHandle(MainHandle) ;
    Log('Trimmed Memory Successfull!');
  except
    Log('Failed to trim Memory!');
  end;
  Application.ProcessMessages;
end;

I tried it out, works perfectly - Even when my app is doing something, and I fire buttonclicks, etc, it still does its thing, and it works like a charm. I look at my apps Memory usage in the Resource Monitor, and as far as I can see, its all good.

So.. Whats the catch? We all deal with memory issues, but is the solution really that simple? Can anyone tell me if doing this every 60 seconds is a bad thing?

I will reboot and try to run my program, and post a screenshot of my Resource Monitor.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Jeff
  • 12,085
  • 12
  • 82
  • 152
  • Instead of OpenProcess, you can just call GetCurrentProcess. It gives you a handle that your process can use in most circumstances to refer to itself, and you don't need to bother with permissions or close it. – Rob Kennedy May 19 '11 at 14:08
  • 2
    And if you are looking for memory issues and think this is a solution, you are looking at the wrong task manager column. Do not look at the Mem Usage/Workingset. That only will tell you what part of the memory currently is in RAM. Look at VM Size/Commit Size. That will tell you what memory your process uses and counts RAM and page file. – Lars Truijens May 19 '11 at 18:30
  • actually `EmptyWorkingSet(GetCurrentProcess);` do exactly the same as `SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);` but as it's explained here; don't use it if you don't have a serious reason for that –  May 20 '11 at 11:01

4 Answers4

36

Yes, it's a bad thing. You're telling the OS that you know more about memory management than it does, which probably isn't true. You're telling to to page all your inactive memory to disk. It obeys. The moment you touch any of that memory again, the OS has to page it back into RAM. You're forcing disk I/O that you don't actually know you need.

If the OS needs more free RAM, it can figure out which memory hasn't been used lately and page it out. That might be from your program, or it might be from some other program. But if the OS doesn't need more free RAM, then you've just forced a bunch of disk I/O that nobody asked for.

If you have memory that you know you don't need anymore, free it. Don't just page it to disk. If you have memory that the OS thinks you don't need, it will page it for you automatically as the need arises.

Also, it's usually unwise to call Application.ProcessMessages unless you know there are messages that your main thread needs to process that it wouldn't otherwise process by itself. The application automatically processes messages when there's nothing else to do, so if you have nothing to do, just let the application run itself.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
6

The "catch" as it were is that you have just told the operating system to remove pages from your working set that are actually in RAM. Assuming the OS is removing pages that don't have data you will ever access again, there's no problem. But if it's paging out data that your process will need in the future, you've just told Windows "More page faults, please."

The main issue with this code is that you're essentially sacrificing your own process's performance for the sake of the rest of the system (though thrashing actually harms the whole system.) That's somewhat noble, but clearly not "catch" free.

dlev
  • 48,024
  • 5
  • 125
  • 132
5

This is the moral equivalent of pretending to the operating system that your machine is an permanent state of RAM crisis. The system knows how to manage its memory far better than you do, just let it get on with its job.

It is, sadly, a very common mistake for people to worry when their system is using all of its RAM and all of its CPU. In reality you should be concerned if your system fails to make full use of its resources!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • ..and, if it isn't broke don't fix it. Unless you encounter memory related issues in your Application, I wouldnt worry too much of handling it yourself. As already said, Windows can take care of this for you, all you need to worry about is freeing/releasing your objects from memory. –  May 19 '11 at 14:21
-1

Actually when using GlobalAlloc/GlobalFree Windows does tend to keep those memory blocks attached to your process, I have had process "appear" to be using 400MB of memory when it was only using 40MB because GlobalFrees do not really release the memory back (we are talking along lived process running in the background as long as the machine is running). In this case I found it very useful to have the ability to tell Windows compact the process memory. I do use the GetProcessMemoryInfo and check the current .WorkingSetSize, if larger than a certain amount (like 100MB) the memory is compacted. Yes, this does incur page faults for memory being actively used but memory is freed back to the kernel for use by other processes.

So, in some cases I found that Windows does not do a good job "garbage collecting" and returning resources. Glad this call is available, it is very useful.

JohnT
  • 1