Hi dk70, this could be used for mem trimming in components:

nsWindow.cpp 27 Oct 200 04:30:54 -0000
@@ -71,6 +71,7 @@
#include “nsTransform2D.h”
#include “nsIEventQueue.h”
#include <windows.h>
+#include <psapi.h>

// unknwn.h is needed to build with WIN32_LEAN_AND_MEAN
#include <unknwn.h>
@@ -275,6 +276,7 @@
static PRUint32 gLastInputEventTime = 0;

static int gTrimOnMinimize = 2; // uninitialized, but still true
+static int gRestoreSavedWorkingSet = 2; // uninitialized, but still true

#if 0
static PRBool is_vk_down(int vk)
@@ -1540,6 +1542,7 @@
(conveniently created before any visible windows and after
the profile has been initialized) */
gTrimOnMinimize = 1;

  • gRestoreSavedWorkingSet = 1;
    nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
    if (prefs) {
    nsCOMPtr prefBranch;
    @@ -1550,6 +1553,11 @@
    &trimOnMinimize))
    && !trimOnMinimize)
    gTrimOnMinimize = 0;

  •    PRBool restoreSavedWorkingSet;
    
  •    if (NS_SUCCEEDED(prefBranch->GetBoolPref("config.restore_saved_workingset",
    
  •                                             &restoreSavedWorkingSet))
    
  •        && !restoreSavedWorkingSet)
    
  •      gRestoreSavedWorkingSet = 0;
     }
    

    }
    }
    @@ -3707,6 +3715,113 @@
    return TRUE;
    }

+static LPDWORD CaptureWorkingSet()
+{

  • SIZE_T dwBufferSize = 4096;
  • LPDWORD lpNewBufferData = (LPDWORD)HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
  • if (!lpNewBufferData) {
  • return NULL;
  • }
  • // Keep enlarging the buffer until we are able to fully retrieve
  • // the working set array.
  • while (!QueryWorkingSet(GetCurrentProcess(), lpNewBufferData, dwBufferSize) ||
  •     (lpNewBufferData[0] + 1) * sizeof(DWORD) > dwBufferSize) {
    
  • dwBufferSize += 4096;
  • if (dwBufferSize > 512*1024) {
  •  HeapFree(GetProcessHeap(), 0, lpNewBufferData);
    
  •  return NULL;
    
  • }
  • LPDWORD lpResizedBuffer = (LPDWORD)HeapReAlloc(GetProcessHeap(), 0, lpNewBufferData, dwBufferSize);
  • if (!lpResizedBuffer) {
  •  HeapFree(GetProcessHeap(), 0, lpNewBufferData);
    
  •  lpResizedBuffer = (LPDWORD)HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
    
  •  if (!lpResizedBuffer) return NULL;
    
  • }
  • lpNewBufferData = lpResizedBuffer;
  • }
  • return lpNewBufferData;
    +}

+static void SaveOrRestoreWorkingSet(BOOL SaveOrRestore)
+{

  • static LPDWORD lpBufferData = NULL;
  • if (SaveOrRestore) {
  • // Save WorkingSet
  • LPDWORD lpNewBufferData = CaptureWorkingSet();
  • if (!lpNewBufferData) return;
  • // Swap in the new working set array, freeing any old one.
  • LPDWORD lpOldBuffer = (LPDWORD)InterlockedExchangePointer(&lpBufferData, lpNewBufferData);
  • if (lpOldBuffer != NULL) {
  •  HeapFree(GetProcessHeap(), 0, lpOldBuffer);
    
  • }
  • } else {
  • // Restore WorkingSet
  • LPDWORD lpLocalData = (LPDWORD)InterlockedExchangePointer(&lpBufferData, NULL);
  • if (lpLocalData != NULL) {

+#if 1

  •  // Capture a fresh copy of the WorkingSet so that we can measure
    
  •  // how much we're swapping in.
    
  •  LPDWORD lpTmpBufferData = CaptureWorkingSet();
    
  •  if (lpTmpBufferData != NULL) {
    
  •    DWORD dwNumPresent = 0;
    
  •    DWORD cPages = lpTmpBufferData[0];    // First DWORD is page count
    
  •    for ( DWORD i = 1; i <= cPages; i++ ) {
    
  •      DWORD pageAddr = lpTmpBufferData[i] & 0xFFFFF000;
    
  •      DWORD pageFlags = lpTmpBufferData[i] & 0x00000FFF;
    
  •      if ((pageFlags & 31) > 0 && (pageFlags & 31) < 16) {
    
  •        dwNumPresent++;
    
  •      }
    
  •    }
    
  •    HeapFree(GetProcessHeap(), 0, lpTmpBufferData);
    
  •    lpTmpBufferData = NULL;
    
  •    char tmpstatus[200];
    
  •    _snprintf(tmpstatus, sizeof(tmpstatus), "There are currently %u pages (%u KB) present.\n", dwNumPresent, 4 * dwNumPresent);
    
  •    OutputDebugString(tmpstatus);
    
  •  }
    

+#endif
+
+

  •  // Start forcing the pages back into memory.
    
  •  DWORD dwNumForced = 0;
    
  •  DWORD cPages = lpLocalData[0];    // First DWORD is page count
    
  •  for ( DWORD i = 1; i <= cPages; i++ ) {
    
  •    DWORD pageAddr = lpLocalData[i] & 0xFFFFF000;
    
  •    DWORD pageFlags = lpLocalData[i] & 0x00000FFF;
    
  •    if ((pageFlags & 31) > 0 && (pageFlags & 31) < 16) {
    
  •      // Force the page to be swapped in.
    
  •      IsBadReadPtr((VOID*)pageAddr, 4096);
    
  •      dwNumForced++;
    
  •    }
    
  •  }
    
  •  // Log how many pages were forced back into memory.
    

+#if 1

  •  char tmpstatus[200];
    
  •  _snprintf(tmpstatus, sizeof(tmpstatus), "Forced %u pages (%u KB) to become present.\n", dwNumForced, 4 * dwNumForced);
    
  •  OutputDebugString(tmpstatus);
    

+#endif
+

  •  // Put this workingset buffer back into the array so that it can
    
  •  // be used again until the workingset is captured again.
    
  •  if (InterlockedCompareExchangePointer((PVOID*)&lpBufferData, lpLocalData, NULL) != NULL) {
    
  •    // the exchange did not occur because a newer buffer was
    
  •    // already put in its place, so just free the older buffer.
    
  •    HeapFree(GetProcessHeap(), 0, lpLocalData);
    
  •  }
    
  • }
  • }
    +}

// Check for pending paints and dispatch any pending paint
// messages for any nsIWidget which is a descendant of the
// top-level window that this window is embedded within.
@@ -4500,6 +4615,17 @@
::ShowWindow(mWnd, SW_SHOWMINIMIZED);
result = PR_TRUE;
}

  •  if (gRestoreSavedWorkingSet) {
    
  •    if (wParam == SC_MINIMIZE) {
    
  •      OutputDebugString("gRestoreSavedWorkingSet is saving the current working set\n");
    
  •      SaveOrRestoreWorkingSet(TRUE);
    
  •      OutputDebugString("gRestoreSavedWorkingSet is done saving\n");
    
  •    } else if (wParam == SC_RESTORE) {
    
  •      OutputDebugString("gRestoreSavedWorkingSet is restoring the original working set\n");
    
  •      SaveOrRestoreWorkingSet(FALSE);
    
  •      OutputDebugString("gRestoreSavedWorkingSet is done restoring\n");
    
  •    }
    
  •  }
     break;
    

    default:


polonus