Author: nextgens
Date: 2007-03-25 14:36:14 +0000 (Sun, 25 Mar 2007)
New Revision: 12372
Modified:
trunk/freenet/src/freenet/node/MemoryChecker.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/NodeStats.java
Log:
Spare YetAnotherThread (MemoryChecker)... move node.aggressiveGCModificator to
node.load.aggressiveGCModificator
Modified: trunk/freenet/src/freenet/node/MemoryChecker.java
===================================================================
--- trunk/freenet/src/freenet/node/MemoryChecker.java 2007-03-25 13:33:50 UTC
(rev 12371)
+++ trunk/freenet/src/freenet/node/MemoryChecker.java 2007-03-25 14:36:14 UTC
(rev 12372)
@@ -4,58 +4,71 @@
package freenet.node;
import freenet.support.Logger;
+import freenet.support.SizeUtil;
public class MemoryChecker implements Runnable {
- private boolean goon = true;
+ private boolean goon = false;
+ private final PacketSender ps;
+ private int aggressiveGCModificator;
- protected void terminate(){
+ public MemoryChecker(PacketSender ps, int modificator){
+ this.ps = ps;
+ this.aggressiveGCModificator = modificator;
+ }
+
+ protected synchronized void terminate() {
goon = false;
+ Logger.normal(this, "Terminating Memory Checker!");
}
+ public boolean isRunning() {
+ return goon;
+ }
+
+ public synchronized void start() {
+ goon = true;
+ Logger.normal(this, "Starting Memory Checker!");
+ run();
+ }
+
public void run() {
+ if(!goon){
+ Logger.normal(this, "Goon is false ; killing
MemoryChecker");
+ return;
+ }
+
Runtime r = Runtime.getRuntime();
- while(goon) {
- int sleeptime = Node.aggressiveGCModificator;
- if(sleeptime <= 0)
- sleeptime = 250;
-
+
+ Logger.normal(this, "Memory in use:
"+SizeUtil.formatSize((r.totalMemory()-r.freeMemory())));
+
+ int sleeptime = aggressiveGCModificator;
+ if(sleeptime <= 0) { // We are done
+ ps.queueTimedJob(this, 120 * 250); // 30 sec
+ return;
+ } else
+ ps.queueTimedJob(this, 120 * sleeptime);
+
+ // FIXME
+ // Do not remove until all known memory issues fixed,
+ // Especially #66
+ // This probably reduces performance, but it makes
+ // memory usage *more predictable*. This will make
+ // tracking down the sort of nasty unpredictable OOMs
+ // we are getting much easier.
+ if(aggressiveGCModificator > 0) {
boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
-
- for(int i=0;i<120;i++) {
- try {
- Thread.sleep(sleeptime);
- } catch (InterruptedException e) {
- // Ignore
- }
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- if(logMINOR)
- Logger.minor(this, "Memory in use:
"+(r.totalMemory()-r.freeMemory()));
+ long beforeGCUsedMemory =
(r.totalMemory()-r.freeMemory());
+ if(logMINOR) Logger.minor(this, "Memory in use before
GC: "+beforeGCUsedMemory);
+ long beforeGCTime = System.currentTimeMillis();
+ System.gc();
+ System.runFinalization();
+ long afterGCTime = System.currentTimeMillis();
+ long afterGCUsedMemory =
(r.totalMemory()-r.freeMemory());
+ if(logMINOR) {
+ Logger.minor(this, "Memory in use after GC:
"+afterGCUsedMemory);
+ Logger.minor(this, "GC completed after
"+(afterGCTime - beforeGCTime)+"ms and \"recovered\" "+(beforeGCUsedMemory -
afterGCUsedMemory)+" bytes, leaving "+afterGCUsedMemory+" bytes used");
}
- try {
- Thread.sleep(sleeptime);
- } catch (InterruptedException e) {
- // Ignore
- }
- // FIXME
- // Do not remove until all known memory issues fixed,
- // Especially #66
- // This probably reduces performance, but it makes
- // memory usage *more predictable*. This will make
- // tracking down the sort of nasty unpredictable OOMs
- // we are getting much easier.
- if(Node.aggressiveGCModificator > 0) {
- long beforeGCUsedMemory =
(r.totalMemory()-r.freeMemory());
- if(logMINOR) Logger.minor(this, "Memory in use
before GC: "+beforeGCUsedMemory);
- long beforeGCTime = System.currentTimeMillis();
- System.gc();
- System.runFinalization();
- long afterGCTime = System.currentTimeMillis();
- long afterGCUsedMemory =
(r.totalMemory()-r.freeMemory());
- if(logMINOR) {
- Logger.minor(this, "Memory in use after
GC: "+afterGCUsedMemory);
- Logger.minor(this, "GC completed after
"+(afterGCTime - beforeGCTime)+"ms and \"recovered\" "+(beforeGCUsedMemory -
afterGCUsedMemory)+" bytes, leaving "+afterGCUsedMemory+" bytes used");
- }
- }
}
+
}
}
\ No newline at end of file
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2007-03-25 13:33:50 UTC (rev
12371)
+++ trunk/freenet/src/freenet/node/Node.java 2007-03-25 14:36:14 UTC (rev
12372)
@@ -177,10 +177,6 @@
/** Log config handler */
public static LoggingConfigHandler logConfigHandler;
- // Enable this if you run into hard to debug OOMs.
- // Disabled to prevent long pauses every 30 seconds.
- static int aggressiveGCModificator = -1 /*250*/;
-
/** If true, local requests and inserts aren't cached.
* This opens up a glaring vulnerability; connected nodes
* can then probe the store, and if the node doesn't have the
@@ -750,20 +746,6 @@
decrementAtMax = random.nextDouble() <= DECREMENT_AT_MAX_PROB;
decrementAtMin = random.nextDouble() <= DECREMENT_AT_MIN_PROB;
- nodeConfig.register("aggressiveGC", aggressiveGCModificator,
sortOrder++, true, false, "AggressiveGC modificator", "Enables the user to
tweak the time in between GC and forced finalization. SHOULD NOT BE CHANGED
unless you know what you're doing! -1 means : disable forced call to
System.gc() and System.runFinalization()",
- new IntCallback() {
- public int get() {
- return aggressiveGCModificator;
- }
- public void set(int val) throws
InvalidConfigValueException {
- if(val == get()) return;
- Logger.normal(this, "Changing
aggressiveGCModificator to "+val);
- aggressiveGCModificator = val;
- }
- });
-
- aggressiveGCModificator = nodeConfig.getInt("aggressiveGC");
-
// FIXME maybe these configs should actually be under a node.ip
subconfig?
ipDetector = new NodeIPDetector(this);
sortOrder = ipDetector.registerConfigs(nodeConfig, sortOrder);
Modified: trunk/freenet/src/freenet/node/NodeStats.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeStats.java 2007-03-25 13:33:50 UTC
(rev 12371)
+++ trunk/freenet/src/freenet/node/NodeStats.java 2007-03-25 14:36:14 UTC
(rev 12372)
@@ -51,7 +51,6 @@
public static final int MAX_INTERREQUEST_TIME = 10*1000;
private final Node node;
- private Thread myMemoryCheckerThread;
private MemoryChecker myMemoryChecker;
public final PeerManager peers;
@@ -135,6 +134,10 @@
final NodePinger nodePinger;
+ // Enable this if you run into hard to debug OOMs.
+ // Disabled to prevent long pauses every 30 seconds.
+ private int aggressiveGCModificator = -1 /*250*/;
+
// Peers stats
/** Next time to update PeerManagerUserAlert stats */
private long nextPeerManagerUserAlertStatsUpdateTime = -1;
@@ -175,34 +178,38 @@
});
threadLimit = statsConfig.getInt("threadLimit");
- statsConfig.register("memoryChecker", true, sortOrder++, true,
false, "Enable the Memory checking thread", "Enable the memory checking
thread",
+ // Yes it could be in seconds insteed of multiples of 0.12, but
we don't want people to play with it :)
+ statsConfig.register("aggressiveGC", aggressiveGCModificator,
sortOrder++, true, false, "AggressiveGC modificator", "Enables the user to
tweak the time in between GC and forced finalization. SHOULD NOT BE CHANGED
unless you know what you're doing! -1 means : disable forced call to
System.gc() and System.runFinalization()",
+ new IntCallback() {
+ public int get() {
+ return aggressiveGCModificator;
+ }
+ public void set(int val) throws
InvalidConfigValueException {
+ if(val == get()) return;
+ Logger.normal(this, "Changing
aggressiveGCModificator to "+val);
+ aggressiveGCModificator = val;
+ }
+ });
+ aggressiveGCModificator = statsConfig.getInt("aggressiveGC");
+
+ myMemoryChecker = new MemoryChecker(node.ps,
aggressiveGCModificator);
+ statsConfig.register("memoryChecker", true, sortOrder++, true,
false, "Enable the Memory check", "Enable the memory check (writes a message in
logfile, mandatory for aggressiveGCModificator to have any effect!)",
new BooleanCallback(){
public boolean get() {
- return (myMemoryCheckerThread
!= null);
+ return
myMemoryChecker.isRunning();
}
public void set(boolean val) throws
InvalidConfigValueException {
if(val == get()) return;
- if(val == false){
+
+ if(val)
+ myMemoryChecker.start();
+ else
myMemoryChecker.terminate();
- myMemoryChecker = null;
- myMemoryCheckerThread =
null;
- } else {
- myMemoryChecker = new
MemoryChecker();
- myMemoryCheckerThread =
new Thread(myMemoryChecker, "Memory checker");
-
myMemoryCheckerThread.setPriority(Thread.MAX_PRIORITY);
-
myMemoryCheckerThread.setDaemon(true);
-
myMemoryCheckerThread.start();
- }
}
});
-
- if(statsConfig.getBoolean("memoryChecker")){
- myMemoryChecker = new MemoryChecker();
- myMemoryCheckerThread = new Thread(myMemoryChecker,
"Memory checker");
- myMemoryCheckerThread.setPriority(Thread.MAX_PRIORITY);
- myMemoryCheckerThread.setDaemon(true);
- }
+ if(statsConfig.getBoolean("memoryChecker"))
+ myMemoryChecker.start();
statsConfig.register("freeHeapBytesThreshold", "5M",
sortOrder++, true, true, "Free heap bytes threshold", "The node will try to
keep it's free heap bytes above the threshold by refusing new requests",
new LongCallback() {