Prevent memory working set minimize in Console application?
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-consol开发者_运维知识库e-a.aspx
Thanks, in advance.
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.
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.
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.
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.
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
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);
精彩评论