memory usage handling improvments

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/ec/trunk@36993 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2013-08-20 14:35:26 +00:00
parent 9c25d16a78
commit e8d0a5efdc
3 changed files with 129 additions and 27 deletions

View file

@ -1,3 +1,11 @@
2013-08-20 Richard Frith-Macdonald <rfm@gnu.org>
* EcConsole.m: Ignore exception printing message on shutdown.
* EcProcess.m: Improve SIGHUP handling. Add new option for
memory usage logging and increase default alert increments
again. Make name of allowed usage config consistent with other
names. Add option to quit process when usage gets too high.
2013-08-05 Richard Frith-Macdonald <rfm@gnu.org>
* AlarmTool.m: Tool to raise/clear alarms

View file

@ -71,15 +71,50 @@
may be overridden by using the 'release' command in the
Console program.
</desc>
<term>EcMemoryAllowed</term>
<desc>
This may be used to specify the heap memory allocation allowed
(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.
</desc>
<term>EcMemoryIncrement</term>
<desc>
This integer value controls the (KBytes) increment in process
memory usage after which an alert is generated.<br />
If this is not set (or is set to a value less than 1) then
a value of 500 is used unless EcMemory is set (in which case
the lower value of 20 is used).<br />
If this is not set (or is set to a value less than ten or
greater than a million) then a value of five thousand is used
unless EcMemory is set (in which case twenty is used).<br />
Setting a higher value make memory leak detection less
sensitive (but reduces unnecessary alerts).<br />
If used in conjunction with EcMemoryPercentage, the greater
of the two allowed memory values is used.<br />
This may be set on the command line or in Control.plist
</desc>
<term>EcMemoryMaximum</term>
<desc>
This may be used to specify the heap memory allocation 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 this is not specified (or a negative value is specified)
the process will never shut down due to excessive memory usage.
</desc>
<term>EcMemoryPercentage</term>
<desc>
This integer value controls the increase in the alerting
threshold after which a memory usage alert is generated.<br />
The increase is calcuilated as a percentage of the current
memory usage value when an alert is generated.<br />
If this is not set (or is set to a value less than one or
greater than a thousand) then a value of ten is used unless
EcMemory is set (in which one is used).<br />
Setting a higher value make memory leak detection less
sensitive (but reduces unnecessary alerts).<br />
If used in conjunction with EcMemoryIncrement, the greater
of the two allowed memory values is used.<br />
This may be set on the command line or in Control.plist
</desc>
<term>EcRelease</term>

View file

@ -1,4 +1,3 @@
/** Enterprise Control Configuration and Logging
Copyright (C) 2012 Free Software Foundation, Inc.
@ -483,11 +482,12 @@ ecHostName()
}
#define DEFMEMALLOWED 50
static int memAllowed = DEFMEMALLOWED;
static int memLast = 0;
static int memPeak = 0;
static int memSlot = 0;
static int memRoll[10];
static uint64_t memMaximum = 0;
static uint64_t memAllowed = DEFMEMALLOWED;
static NSUInteger memLast = 0;
static NSUInteger memPeak = 0;
static NSUInteger memSlot = 0;
static NSUInteger memRoll[10];
#define memSize (sizeof(memRoll)/sizeof(*memRoll))
@ -1103,14 +1103,16 @@ static NSString *noFiles = @"No log files to archive";
[self setCmdInterval: [str floatValue]];
}
str = [cmdDefs stringForKey: @"MemAllowed"];
if (nil != str)
memAllowed = (uint64_t)[cmdDefs integerForKey: @"MemoryAllowed"];
if (0 == memAllowed || memAllowed > 100000)
{
memAllowed = [str intValue];
if (memAllowed <= 0)
{
memAllowed = DEFMEMALLOWED; // Fifty megabytes default
}
memAllowed = DEFMEMALLOWED; // Fifty megabytes default
}
memMaximum = (uint64_t)[cmdDefs integerForKey: @"MemoryMaximum"];
if (memMaximum > 100000)
{
memMaximum = 0; // Disabled
}
str = [cmdDefs stringForKey: @"CoreSize"];
@ -1895,6 +1897,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
{
NSLog(@"Rejected by Command - %@",
[r objectForKey: @"rejected"]);
cmdIsQuitting = YES;
[self cmdQuit: 0]; /* Rejected by server. */
}
else if (nil == r || nil == [r objectForKey: @"back-off"])
@ -1988,11 +1991,25 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
struct mallinfo info;
info = mallinfo();
/* Do initial population so we can work immediately.
*/
if (0 == memRoll[0])
{
int b = info.uordblks;
if (b <= 0) b = 1;
while (memSlot < memSize)
{
memRoll[memSlot++] = b;
}
memLast = b;
memPeak = b;
}
if (memSlot >= memSize)
{
NSUInteger average;
NSUInteger notLeaked;
int i;
int i;
notLeaked = [self ecNotLeaked];
@ -2021,7 +2038,10 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
average = ((average / 1024) + 1) * 1024;
if (average > memPeak)
{
int inc;
NSInteger inc;
NSInteger pct;
NSInteger iMax = 0;
NSInteger pMax = 0;
/* Alert if the we have peaked above the allowed size.
*/
@ -2044,8 +2064,28 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
memPeak = size;
}
}
inc = (int)[cmdDefs integerForKey: @"MemoryIncrement"];
if (inc < 1)
/* 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)
{
if (NO == cmdIsQuitting)
{
cmdIsQuitting = YES;
[self cmdQuit: -1];
}
}
/* 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)
{
if (YES == [cmdDefs boolForKey: @"Memory"])
{
@ -2054,6 +2094,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
* peak usage.
*/
inc = 20;
pct = 0;
}
else
{
@ -2063,10 +2104,19 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
* ensuring that only serious increases
* in usage will generate an alert.
*/
inc = 5120;
inc = 5000;
pct = 10; // Use ten percent if more than fixed increment
}
}
memPeak = ((memPeak / (inc * 1024)) + 2) * (inc * 1024);
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.
@ -2161,6 +2211,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
int sig = cmdSignalled;
cmdSignalled = 0;
cmdIsQuitting = YES;
[self cmdQuit: sig];
}
}
@ -2176,6 +2227,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
/* finish server */
cmdIsQuitting = YES;
[self cmdQuit: 0];
DESTROY(EcProcConnection);
return 0;
@ -2970,11 +3022,16 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
}
}
if (YES == [cmdDefs boolForKey: @"Memory"])
{
[self cmdPrintf: @"Memory usage: %u (peak), %u (current)\n",
memPeak, memLast];
}
[self cmdPrintf: @"Memory usage: %"PRIuPTR" (peak), %"PRIuPTR
" (current), %"PRIuPTR" (exempt)\n",
memPeak, memLast, [self ecNotLeaked]];
[self cmdPrintf:
@"Memory error reporting after usage: %"PRIu64"MB\n", memAllowed];
if (memMaximum > 0)
{
[self cmdPrintf:
@"Memory usage exceeded shutdown after: %"PRIu64"MB\n", memMaximum];
}
}
}
@ -3869,6 +3926,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
cmdPTimer = nil;
if (sig > 0)
{
cmdIsQuitting = YES;
[self cmdQuit: sig];
}
if (YES == inProgress)
@ -4071,6 +4129,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
additionalText: err];
[self alarm: a];
[alarmDestination shutdown];
cmdIsQuitting = YES;
[self cmdQuit: 1];
}
else