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() {


Reply via email to