views:

410

answers:

6

Hi, I want to prevent memory working set minimize in Console application. In windows application, I can do by overriding SC_MINIMIZE messages. But, how can I intercept SC_MINIMIZE in console application? Or, can I prevent memory working set minimize by other ways?

I use Visual Studio 2005 C++. Somebody has some problem, and the solution is not pleasing. :( http://www.eggheadcafe.com/software/aspnet/30953826/working-set-and-console-a.aspx

Thanks, in advance.

+1  A: 

Console applications do not receive window messages, as such there is no way to determine if the application is in front of the user or not. You will have to develop other strategies (perhaps a user activity timer) in order to deallocate memory when the application is not in use.

You can also implement your own Console-like wrapper, but this is not a easy task to get correct.

Yann Ramin
P-P asked how *not* to minimize the working-set size.
Rob Kennedy
+2  A: 

Since console applications by default doesnt have message loop running, hence you would not be able to have access to standard windows messages in your console application.

Kavitesh Singh
-1 for not explaining why console applications are unable to process window messages
George Edison
Actually, it is perfectly possible to access the Windows message queue in a console application. All Win32 APIs are available to Console apps. Intercepting a message inside the compiler-runtime-provided WinMain message loop is probably tricky and crash-prone, but displaying a dialog and processing already-dispatched messages isn't all that unusual in a console app - some console apps are GUI apps too. There's probably APIs to work with console windows in GUI apps - which the standard console-app runtime probably calls.
Steve314
Mind you - that's **not** a recommended answer to the current question.
Steve314
@George: If you can check the question again, it never asked why console doesnt have a message loop. I have tried to answer that in console you generally dont have a message loop hence you may not have direct access to SC_MINIMIZE message. Ofcourse you can hack and do some lower level programming to get all the messages but i dont know how relevant that would have been or worth the effort. @Steve314: I never said my answer was the best or recommended. You do realize i cant upvote my own answers. So some people may have appreciate the point i mentioned here.
Kavitesh Singh
+3  A: 

SetProcessWorkingSetSize(Ex) or use VirtualLock on the range you want to keep in physical memory.

Both will negatively affect system performance under load, but I suspect you don't care about that right now.

MSN
A: 

you can use a very sneaky/hacky work around for this, which might be your only way:

SetConsoleTitle("MyConsole"); //at creation
//... 
HWND hWnd = FindWindow(NULL,"MyConsole"); //when it would minimize
ShowWindow(hWnd,SW_MAXIMIZE);

you could even fiddle with some of the window properties using the HWND as well

Necrolis
+3  A: 

Working set trimming can only be prevented by locking pages in memory, either by locking them explictly with VirtualLock or by mapping memory into AWE. But both operations are extreamly high priviledged and require the application to run under an account that is granted the 'Lock Pages in Memory' priviledge, see How to: Enable the Lock Pages in Memory Option. By default nobody, not vene administrators, have this priviledge.

Technically, that is the answer you are looking for (ommitting the 'minor' details of how to identify the regions to lock). But your question indicates that you are on a totaly wrong path.

Wroking set trimming is something that occurs frequently and has no serious adverse effects. You are most likely confusing the trimming with paging out the memory, but they are distinct phases of the memory page lifetime. Trimming occurs when the OS takes away the mapping of the page from the process and places the page into a standby list. This is a very fast and simple operation: the page is added into the standby list and the pte is marked accordingly. No IO operation occurs, the physical RAM content is not changed. When, and if, the process accesses the trimmed page again a soft fault will occur. The TLB miss will trigger a walk into the kernel land, the kernel will locate the page in the standby list and it will re-allocate it to the process. Fast, quick, easy, again, no IO operation occurs, nor any RAM content changes for the page. So a process that has all its working set trimmed will regain the entire active set fairly quickly (microseconds) if it keeps referencing the pages.

Only when the OS needs new pages for its free list will it look into the standby list, take the oldest page and actually swap it to disk. In this situation indeed IO occurs and the RAM content is zero-ed out. When the process accesses again the page a hard fault will occur. The TLB miss will wake the kernel, this will inspect the pte's list and now a 'real' page fault will occur: a new free page is allocate, the content is read from the disk, and then the page is allocated to the process and the execution resumes from the TLB miss location.

As you can see, there is a huge difference between the working set trimming and a memory pressure page swap. If your console application is trimmed, don't sweat over it. You will do incalculable more damage to the system health by locking pages in memory. And btw, you also do a similar bad user experience by refusing to minimize when asked to, just because you misunderstand the page life cycle.

It is true that there are processes that have a legitimate demand to keep their working set as hot as possible. All those processes, always, are implemented as services. Services benefit from a more lenient trimming policy from the OS, and this policy is actually configurable.

If you are really concerned about the system memory and want to help the OS you should register for memory notifications using CreateMemoryResourceNotification and react to memory pressure by freeing your caches, and grow your caches back when your notified that free memory is available.

Remus Rusanu
it's for server programming, so I want to keep it's memory as hot as possible.But it's not desearve to be service program(it's just load data for other programs).
P-P
Given your other question about 1Gb memory mapped file, you probably know exactly the region to lock. Use VirtualLock, but be weary of the impact on the system. Preventing the console from minimize will, at best, prevent the console from minimize, but you may still loose memory to the workset trimming. VirtualLock will guarantee the MMF to stay in RAM. But again, the cost and consequences may well outweight the benefits.
Remus Rusanu
A: 

How about disabling minimize in the Console's system menu?

HWND hwnd = GetConsoleWindow(void);
HMENU hmenu = GetSystemMenu(hwnd, FALSE);
EnableMenuItem (hmenu, SC_MINIMIZE, MF_DISABLED | MF_BYCOMMAND);

You could also try disabling the minimize button on your console window.

HWND hwnd = GetConsoleWindow(void);
LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, lStyle & ~WS_MINIMIZEBOX);
John Knoeller
I tried, but it doesn't work. :(
P-P
Let me guess, you are running Vista or Win7 right?
John Knoeller
I make a win32 project(MSVC2005 sp1). OS is Windows XP sp3.I put your code after _tmain but I can minimize my console and working memory is trimmed.
P-P