Author: rfm
Date: Fri Jul  3 21:23:42 2015
New Revision: 38748

URL: http://svn.gna.org/viewcvs/gnustep?rev=38748&view=rev
Log:
redo memory management to be easier to use

Modified:
    libs/ec/trunk/ChangeLog
    libs/ec/trunk/EcProcess.h
    libs/ec/trunk/EcProcess.m

Modified: libs/ec/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/ChangeLog?rev=38748&r1=38747&r2=38748&view=diff
==============================================================================
--- libs/ec/trunk/ChangeLog     (original)
+++ libs/ec/trunk/ChangeLog     Fri Jul  3 21:23:42 2015
@@ -1,3 +1,10 @@
+2015-07-03  Richard Frith-Macdonald <[email protected]>
+
+       * EcProcess.h:
+       * EcProcess.m:
+       Revamp memory handling code to work with total process memory rather
+       than heap size.  Report usage in same units as the 'ps' command.
+
 2015-06-17  Richard Frith-Macdonald <[email protected]>
 
        * EcAlarmSinkSNMP.m: Fix stupid mistake setting notificationID.

Modified: libs/ec/trunk/EcProcess.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcProcess.h?rev=38748&r1=38747&r2=38748&view=diff
==============================================================================
--- libs/ec/trunk/EcProcess.h   (original)
+++ libs/ec/trunk/EcProcess.h   Fri Jul  3 21:23:42 2015
@@ -54,7 +54,7 @@
            <desc>
              Specifies the maximum size (in MB) for any core-dump of the
               process.<br />
-              If this is not set, the default size of 1GB is used.<br />
+              If this is not set, the default size of 2GB is used.<br />
               If this is negative, the size is unlimited.<br />
              If this is zero then no core dumping is performed.
            </desc>
@@ -94,10 +94,10 @@
            </desc>
            <term>EcMemoryAllowed</term>
            <desc>
-              This may be used to specify the heap memory allocation allowed
+              This may be used to specify the total process memory usage
               (in megabytes) before memory usage alerting may begin.<br />
               If this is not specified (or a negative value is specified)
-              the default of 50 megabytes is used.
+              the default of 500 megabytes is used.
            </desc>
            <term>EcMemoryIncrement</term>
            <desc>
@@ -114,12 +114,11 @@
            </desc>
            <term>EcMemoryMaximum</term>
            <desc>
-              This may be used to specify the heap memory allocation allowed
+              This may be used to specify the total process memory allowed
               (in megabytes) before the process is forced to quit due to
               excessive memory usage.<br />
-              If the memory usage (heap usage minus -ecNotLeaked) reaches
-              this threshold, the -cmdQuit: method will be called with an
-              argument of -1.<br />
+              If the total memory usage of the process reaches this threshold,
+              the -cmdQuit: method will be called with an argument of -1.<br />
               If this is not specified (or a negative value is specified)
               the process will never shut down due to excessive memory usage.
             </desc>

Modified: libs/ec/trunk/EcProcess.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcProcess.m?rev=38748&r1=38747&r2=38748&view=diff
==============================================================================
--- libs/ec/trunk/EcProcess.m   (original)
+++ libs/ec/trunk/EcProcess.m   Fri Jul  3 21:23:42 2015
@@ -60,8 +60,6 @@
 #import "EcUserDefaults.h"
 #import "EcBroadcastProxy.h"
 
-#include "malloc.h"
-
 #include "config.h"
 
 #ifdef HAVE_SYS_SIGNAL_H
@@ -85,6 +83,7 @@
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif
+#include <stdio.h>
 
 
 
@@ -183,7 +182,7 @@
    * have interrupted some vital library (eg malloc()) and left it in a
    * state such that our code can't continue.  For instance if we try to
    * cleanup after a signal and call free(), the process may hang waiting
-   * for a lock that the interupted malloc() functioin still holds.
+   * for a lock that the interupted function still holds.
    */
   if (0 == cmdSignalled)
     {
@@ -518,14 +517,16 @@
   return [name autorelease];
 }
 
-#define        DEFMEMALLOWED   50
+#define        DEFMEMALLOWED   500
 static NSUInteger       memMaximum = 0;
 static NSUInteger      memAllowed = DEFMEMALLOWED;      // In KB
+static NSUInteger      memAvge = 0;
 static NSUInteger      memLast = 0;
 static NSUInteger      memPeak = 0;
+static NSUInteger      memWarn = 0;
 static NSUInteger      memSlot = 0;
 static NSUInteger      memRoll[10];
-#define        memSize (sizeof(memRoll)/sizeof(*memRoll))
+#define        MEMCOUNT (sizeof(memRoll)/sizeof(*memRoll))
 
 #ifndef __MINGW__
 static int              reservedPipe[2] = { 0, 0 };
@@ -1258,13 +1259,13 @@
 #endif
 
   memAllowed = (NSUInteger)[cmdDefs integerForKey: @"MemoryAllowed"];
-  if (0 == memAllowed || memAllowed > 100000)
-    {
-      memAllowed = DEFMEMALLOWED;      // Fifty megabytes default
+  if (0 == memAllowed || memAllowed > 200000)
+    {
+      memAllowed = DEFMEMALLOWED;
     }
 
   memMaximum = (NSUInteger)[cmdDefs integerForKey: @"MemoryMaximum"];
-  if (memMaximum > 100000)
+  if (memMaximum > 200000)
     {
       memMaximum = 0;                  // Disabled
     }
@@ -1272,7 +1273,7 @@
   str = [cmdDefs stringForKey: @"CoreSize"];
   if (nil == str)
     {
-      i = 1024;         // 1 GB default
+      i = 2*1024;       // 2 GB default
     }
   else
     {
@@ -2223,8 +2224,8 @@
 
 - (void) ecNewMinute: (NSCalendarDate*)when
 {
-  struct mallinfo      info;
-  NSUInteger            bytes;
+  FILE          *fptr;
+  int          i;
 
 #ifndef __MINGW__
   if (NO == cmdIsQuitting)
@@ -2280,153 +2281,138 @@
    */
   [NSHost flushHostCache];
 
-  info = mallinfo();
-  bytes = info.uordblks + info.hblkhd;
-  if (bytes <= 0) bytes = 1;
+  /* /proc/pid/statm reports the process memory size in 4KB pages
+   */
+  fptr = fopen([[NSString stringWithFormat: @"/proc/%d/statm",
+    [[NSProcessInfo processInfo] processIdentifier]] UTF8String], "r");
+  memLast = 1;
+  if (NULL != fptr)
+    {
+      if (fscanf(fptr, "%"PRIuPTR, &memLast) != 1)
+        {
+          memLast = 1;
+        }
+      else
+        {
+          memLast *= (4 * 1024);
+          if (memLast <= 0) memLast = 1;
+        }
+      fclose(fptr);
+    }
 
   /* Do initial population so we can work immediately.
    */
   if (0 == memRoll[0])
     {
-      while (memSlot < memSize)
+      for (i = 0; i < MEMCOUNT; i++)
         {
-          memRoll[memSlot++] = bytes;
+          memRoll[i] = memLast;
         }
-      memLast = bytes;
-      memPeak = bytes;
-    }
-  if (memSlot >= memSize)
-    {
-      NSUInteger       average;
-      NSUInteger       notLeaked;
-      int              i;
-
-      notLeaked = [self ecNotLeaked];
-
-      /* Next slot to record in will be zero.
-       */
-      memSlot = 0;
+      memAvge = memLast;
+    }
+  else
+    {
+      if (memSlot >= MEMCOUNT)
+        {
+          /* Next slot to record in will be zero.
+           */
+          memSlot = 0;
+        }
+      memRoll[memSlot++] = memLast;
 
       /* Find the average usage over the last set of samples.
        * Round up to a block size.
        */
-      for (average = i = 0; i < memSize; i++)
-       {
-         average += memRoll[i];
-       }
-      average /= memSize;
-
-      /* The cache size should probably be less than the heap usage 
-       * though some objects in the cache could actually be using
-       * memory which didn't come from the heap, so subtracting one
-       * from the other is not completely reliable.
+      memAvge = 0;
+      for (i = 0; i < MEMCOUNT; i++)
+        {
+          memAvge += memRoll[i];
+        }
+      memAvge /= MEMCOUNT;
+    }
+  /* Convert to 1KB blocks.
+   */
+  memAvge = ((memAvge / 1024) + 1) * 1024;
+
+  /* If we have a defined maximum memory usage for the process,
+   * we should shut down with a non-zero status to get a restart.
+   */
+  if (memLast > memPeak)
+    {
+      memPeak = memLast;
+    }
+  if (memMaximum > 0 && memPeak > (memMaximum * 1024 * 1024))
+    {
+      if (NO == cmdIsQuitting)
+        {
+          cmdIsQuitting = YES;
+          [self cmdQuit: -1];
+        }
+    }
+
+  if (memWarn < (memAllowed * 1024 * 1024))
+    {
+      memWarn = (memAllowed * 1024 * 1024);
+    }
+  if (memAvge > memWarn)
+    {
+      NSInteger     inc;
+      NSInteger     pct;
+      NSInteger     iMax = 0;
+      NSInteger     pMax = 0;
+
+      /* Alert if the average has risen above the allowed size.
        */
-      average = (notLeaked < average) ? average - notLeaked : 0;
-
-      /* Convert to 1KB blocks.
+      [self cmdError: @"Average heap usage grown to %"PRIuPTR"KB",
+        memAvge / 1024];
+
+      /* We increase the threshold for the next alert by a percentage
+       * of the existing usage or by a fixed increment, whichever is
+       * the larger.
        */
-      average = ((average / 1024) + 1) * 1024;
-      if (average > memPeak)
-       {
-          NSInteger     inc;
-          NSInteger     pct;
-          NSInteger     iMax = 0;
-          NSInteger     pMax = 0;
-
-         /* Alert if the we have peaked above the allowed size.
-          */
-         if (average > (memAllowed * 1024 * 1024))
-           {
-              if (notLeaked > 1024)
-                {
-                  [self cmdError: @"Average heap usage grown to %"PRIuPTR
-                    "KB (plus %"PRIuPTR"KB not leaked)",
-                    average / 1024, notLeaked / 1024];
-                }
-              else
-                {
-                  [self cmdError: @"Average heap usage grown to %"PRIuPTR"KB",
-                    average / 1024];
-                }
-           }
-
-         /* Set the peak memory from the last set of readings.
-          */
-         memLast = memPeak;
-         for (i = 0; i < memSize; i++)
-           {
-             unsigned  size = memRoll[i];
-
-             size = (notLeaked < size) ? size - notLeaked : 0;
-             if (size > memPeak)
-               {
-                 memPeak = size;
-               }
-           }
-
-          /* If we have a defined maximum memory usage for the process,
-           * we should shut down with a non-zero status to get a restart.
-           */
-          if (memMaximum > 0 && memPeak > (memMaximum * 1024 * 1024))
+      pct = [cmdDefs integerForKey: @"MemoryPercentage"];
+      if (pct < 1 || pct > 1000) pct = 0;
+      inc = [cmdDefs integerForKey: @"MemoryIncrement"];
+      if (inc < 10 || inc > 1000000) inc = 0;
+      if (0 == inc && 0 == pct)
+        {
+          if (YES == [cmdDefs boolForKey: @"Memory"])
             {
-              if (NO == cmdIsQuitting)
-                {
-                  cmdIsQuitting = YES;
-                  [self cmdQuit: -1];
-                }
+              /* We want detailed memory information, so we set the next
+               * alerting threshold from 20 to 40 KB above the current
+               * peak usage.
+               */
+              inc = 20;
+              pct = 0;
             }
-
-          /* We increase the threshold for the next alert by a percentage
-           * of the existing usage or by a fixed increment, whichever is
-           * the larger.
-           */
-          pct = [cmdDefs integerForKey: @"MemoryPercentage"];
-          if (pct < 1 || pct > 1000) pct = 0;
-          inc = [cmdDefs integerForKey: @"MemoryIncrement"];
-          if (inc < 10 || inc > 1000000) inc = 0;
-          if (0 == inc && 0 == pct)
+          else
             {
-              if (YES == [cmdDefs boolForKey: @"Memory"])
-                {
-                  /* We want detailed memory information, so we set the next
-                   * alerting threshold from 20 to 40 KB above the current
-                   * peak usage.
-                   */
-                  inc = 20;
-                  pct = 0;
-                }
-              else
-                {
-                  /* We do not want detailed memory information,
-                   * so we set the next alerting threshold from
-                   * 5 to 10 MB above the current peak usage,
-                   * ensuring that only serious increases
-                   * in usage will generate an alert.
-                   */
-                  inc = 5000;
-                  pct = 10;     // Use ten percent if more than fixed increment
-                }
+              /* We do not want detailed memory information,
+               * so we set the next alerting threshold from
+               * 5 to 10 MB above the current peak usage,
+               * ensuring that only serious increases
+               * in usage will generate an alert.
+               */
+              inc = 5000;
+              pct = 10;     // Use ten percent if more than fixed increment
             }
-          if (inc > 0)
-            {
-              iMax = ((memPeak / (inc * 1024)) + 2) * (inc * 1024);
-            }
-          if (pct > 0)
-            {
-              pMax = (((memPeak * (100 + pct)) / 1024 + 1) * 1024);
-            }
-          memPeak = (iMax > pMax) ? iMax : pMax;
-       }
-    }
-  /* Record the latest memory usage.
-   */
-  memRoll[memSlot] = bytes;
+        }
+      if (inc > 0)
+        {
+          iMax = ((memWarn / (inc * 1024)) + 2) * (inc * 1024);
+        }
+      if (pct > 0)
+        {
+          pMax = (((memWarn * (100 + pct)) / 1024 + 1) * 1024);
+        }
+      memWarn = (iMax > pMax) ? iMax : pMax;
+    }
+
   if (YES == [cmdDefs boolForKey: @"Memory"])
     {
       [self cmdDbg: cmdDetailDbg
-              msg: @"Memory usage %"PRIuPTR, memRoll[memSlot]];
-    }
-  memSlot++;
+              msg: @"Memory usage %"PRIuPTR, memLast];
+    }
 
   return;
 }
@@ -3410,9 +3396,12 @@
            }
        }
 
-      [self cmdPrintf: @"Memory usage: %"PRIuPTR"KB (peak), %"PRIuPTR
-        "KB (current), %"PRIuPTR"KB (exempt)\n",
-        memPeak / 1024, memLast / 1024, [self ecNotLeaked] / 1024];
+      [self cmdPrintf: @"Memory usage: %"PRIuPTR"KB (current),"
+        @" %"PRIuPTR"KB (peak)\n",
+        memLast/1024, memPeak/1024];
+      [self cmdPrintf: @"              %"PRIuPTR"KB (average),"
+        @" %"PRIuPTR"KB (exempt)\n",
+        memAvge/1024, [self ecNotLeaked]/1024];
       [self cmdPrintf:
         @"Memory error reporting after usage: %"PRIuPTR"KB\n",
         memAllowed * 1024];


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to