diff --git a/htroot/Performance_p.html b/htroot/Performance_p.html index ff4f43df8..cc8792e05 100644 --- a/htroot/Performance_p.html +++ b/htroot/Performance_p.html @@ -21,10 +21,12 @@ Total
Cycles Idle
Cycles Busy
Cycles +Short Mem
Cycles Sleep Time
per Cycle
(milliseconds) Exec Time
per Busy-Cycle
(milliseconds) Delay between
idle loops Delay between
busy loops +Minimum of
Required Memory Full Description #{table}# @@ -40,10 +42,12 @@ #[totalcycles]# #[idlecycles]# #[busycycles]# +#[memscycles]# #[sleeppercycle]# #[execpercycle]# milliseconds milliseconds + bytes #[longdescr]# #{/table}# diff --git a/htroot/Performance_p.java b/htroot/Performance_p.java index a5cad4b20..67d2c5725 100644 --- a/htroot/Performance_p.java +++ b/htroot/Performance_p.java @@ -81,11 +81,11 @@ public class Performance_p { // set templates for latest news from the threads long blocktime, sleeptime, exectime; - long idlesleep, busysleep; + long idlesleep, busysleep, memprereq; int queuesize; threads = switchboard.threadNames(); int c = 0; - long idleCycles, busyCycles; + long idleCycles, busyCycles, memshortageCycles; while (threads.hasNext()) { threadName = (String) threads.next(); thread = switchboard.getThread(threadName); @@ -102,37 +102,43 @@ public class Performance_p { exectime = thread.getExecTime(); idleCycles = thread.getIdleCycles(); busyCycles = thread.getBusyCycles(); + memshortageCycles = thread.getOutOfMemoryCycles(); prop.put("table_" + c + "_blocktime", blocktime / 1000); prop.put("table_" + c + "_blockpercent", "" + (100 * blocktime / blocktime_total)); prop.put("table_" + c + "_sleeptime", sleeptime / 1000); prop.put("table_" + c + "_sleeppercent", "" + (100 * sleeptime / sleeptime_total)); prop.put("table_" + c + "_exectime", exectime / 1000); prop.put("table_" + c + "_execpercent", "" + (100 * exectime / exectime_total)); - prop.put("table_" + c + "_totalcycles", "" + (idleCycles + busyCycles)); + prop.put("table_" + c + "_totalcycles", "" + (idleCycles + busyCycles + memshortageCycles)); prop.put("table_" + c + "_idlecycles", "" + idleCycles); prop.put("table_" + c + "_busycycles", "" + busyCycles); + prop.put("table_" + c + "_memscycles", "" + memshortageCycles); prop.put("table_" + c + "_sleeppercycle", ((idleCycles + busyCycles) == 0) ? "-" : ("" + (sleeptime / (idleCycles + busyCycles)))); prop.put("table_" + c + "_execpercycle", (busyCycles == 0) ? "-" : ("" + (exectime / busyCycles))); if ((post != null) && (post.containsKey("delaysubmit"))) { // load with new values - idlesleep = Long.parseLong((String) post.get(threadName + "_idlesleep", "1")); - busysleep = Long.parseLong((String) post.get(threadName + "_busysleep", "1")); - + idlesleep = Long.parseLong((String) post.get(threadName + "_idlesleep", "100")); + busysleep = Long.parseLong((String) post.get(threadName + "_busysleep", "1000")); + memprereq = Long.parseLong((String) post.get(threadName + "_memprereq", "0")); + // check values to prevent short-cut loops if (idlesleep == 0) idlesleep = 1000; // on-the-fly re-configuration - switchboard.setThreadSleep(threadName, idlesleep, busysleep); + switchboard.setThreadPerformance(threadName, idlesleep, busysleep, memprereq); switchboard.setConfig(threadName + "_idlesleep", idlesleep); switchboard.setConfig(threadName + "_busysleep", busysleep); + switchboard.setConfig(threadName + "_memprereq", memprereq); } else { // load with old values idlesleep = Long.parseLong(switchboard.getConfig(threadName + "_idlesleep" , "1000")); busysleep = Long.parseLong(switchboard.getConfig(threadName + "_busysleep", "1000")); + memprereq = Long.parseLong(switchboard.getConfig(threadName + "_memprereq", "1000")); } prop.put("table_" + c + "_idlesleep", idlesleep); prop.put("table_" + c + "_busysleep", busysleep); + prop.put("table_" + c + "_memprereq", memprereq); c++; } diff --git a/source/de/anomic/kelondro/kelondroRecords.java b/source/de/anomic/kelondro/kelondroRecords.java index 524f2d774..e7eb8c184 100644 --- a/source/de/anomic/kelondro/kelondroRecords.java +++ b/source/de/anomic/kelondro/kelondroRecords.java @@ -77,8 +77,9 @@ import java.util.StringTokenizer; public class kelondroRecords { // constants - private static int NUL = Integer.MIN_VALUE; // the meta value for the kelondroRecords' NUL abstraction - + private static final int NUL = Integer.MIN_VALUE; // the meta value for the kelondroRecords' NUL abstraction + public static final long memBlock = 5000000; // do not fill cache further if the amount of available memory is less that this + // static seek pointers private static long POS_MAGIC = 0; // 1 byte, byte: file type magic private static long POS_BUSY = POS_MAGIC + 1; // 1 byte, byte: marker for synchronization @@ -352,10 +353,12 @@ public class kelondroRecords { // check for space in cache // should be only called within a synchronized(XcacheHeaders) environment if (XcacheSize == 0) return; - while (XcacheHeaders.size() >= XcacheSize) { + Handle delkey; + while ((XcacheHeaders.size() >= XcacheSize) || + ((XcacheHeaders.size() > 0) && (Runtime.getRuntime().freeMemory() < memBlock))) { // delete one entry try { - Handle delkey = (Handle) XcacheScore.getMinObject(); // error (see below) here + delkey = (Handle) XcacheScore.getMinObject(); // error (see below) here XcacheScore.deleteScore(delkey); XcacheHeaders.remove(delkey); } catch (NoSuchElementException e) { @@ -365,6 +368,7 @@ public class kelondroRecords { this.XcacheScore = new kelondroMScoreCluster(); this.XcacheHeaders = new HashMap(); } + delkey = null; } } @@ -662,6 +666,7 @@ public class kelondroRecords { synchronized (XcacheHeaders) { // remember size to evaluate a cache size check need int sizeBefore = XcacheHeaders.size(); + //long memBefore = Runtime.getRuntime().freeMemory(); // generate cache entry byte[][] cacheValue; if (values == null) { @@ -676,10 +681,11 @@ public class kelondroRecords { cacheNode.ohBytes = this.ohBytes; cacheNode.ohHandle = this.ohHandle; // store the cache entry - XcacheHeaders.put(cacheNode.handle, cacheNode); - XcacheScore.setScore(handle, (int) ((System.currentTimeMillis() - XcacheStartup) / 1000)); + boolean newentry = XcacheHeaders.put(cacheNode.handle, cacheNode) == null; + XcacheScore.setScore(cacheNode.handle, (int) ((System.currentTimeMillis() - XcacheStartup) / 1000)); // delete the cache entry cacheNode = null; + //System.out.println("kelondroRecords cache4" + filename + ": cache record size = " + (memBefore - Runtime.getRuntime().freeMemory()) + " bytes" + ((newentry) ? " new" : "")); // check cache size if (XcacheHeaders.size() > sizeBefore) checkCacheSpace(); //System.out.println("kelondroRecords cache4" + filename + ": " + XcacheHeaders.size() + " entries, " + XcacheSize + " allowed."); diff --git a/source/de/anomic/plasma/plasmaSwitchboard.java b/source/de/anomic/plasma/plasmaSwitchboard.java index af1d913e1..d12c3d781 100644 --- a/source/de/anomic/plasma/plasmaSwitchboard.java +++ b/source/de/anomic/plasma/plasmaSwitchboard.java @@ -148,7 +148,7 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser // load slots - public static int crawlSlots = 20; + public static int crawlSlots = 12; // couloured list management public static TreeSet blueList = null; @@ -578,12 +578,6 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser //log.logDebug("CoreCrawl: queue is empty"); return false; } - if (Runtime.getRuntime().freeMemory() < 2000000) { - log.logDebug("CoreCrawl: not enough memory available, dismissed (" + - "free=" + Runtime.getRuntime().freeMemory() + ")"); - System.gc(); - return false; - } if (queueStack.size() >= crawlSlots) { log.logDebug("CoreCrawl: too many processes in queue, dismissed (" + "queueStack=" + queueStack.size() + ")"); @@ -639,12 +633,6 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser //log.logDebug("LimitCrawl: queue is empty"); return false; } - if (Runtime.getRuntime().freeMemory() < 2000000) { - log.logDebug("limitCrawlTrigger: not enough memory available, dismissed (" + - "free=" + Runtime.getRuntime().freeMemory() + ")"); - System.gc(); - return false; - } // if the server is busy, we do crawling more slowly //if (!(cacheManager.idle())) try {Thread.currentThread().sleep(2000);} catch (InterruptedException e) {} @@ -717,12 +705,6 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser //log.logDebug("GlobalCrawl: queue is empty"); return false; } - if (Runtime.getRuntime().freeMemory() < 2000000) { - log.logDebug("remoteTriggeredCrawl: not enough memory available, dismissed (" + - "free=" + Runtime.getRuntime().freeMemory() + ")"); - System.gc(); - return false; - } /* if (queueStack.size() > 0) { log.logDebug("GlobalCrawl: any processe is in queue, dismissed (" + diff --git a/source/de/anomic/server/serverAbstractSwitch.java b/source/de/anomic/server/serverAbstractSwitch.java index 274c70155..03e563076 100644 --- a/source/de/anomic/server/serverAbstractSwitch.java +++ b/source/de/anomic/server/serverAbstractSwitch.java @@ -254,31 +254,52 @@ public abstract class serverAbstractSwitch implements serverSwitch { log.logInfo("Undeployed Action '" + action.getShortDescription() + "', (" + switchActions.size() + " actions registered)"); } - public void deployThread(String threadName, String threadShortDescription, String threadLongDescription, serverThread newThread, long startupDelay) { + public void deployThread( + String threadName, + String threadShortDescription, + String threadLongDescription, + serverThread newThread, + long startupDelay) { deployThread(threadName, threadShortDescription, threadLongDescription, newThread, startupDelay, - Long.parseLong(getConfig(threadName + "_idlesleep" , "novalue")), - Long.parseLong(getConfig(threadName + "_busysleep" , "novalue"))); + Long.parseLong(getConfig(threadName + "_idlesleep" , "100")), + Long.parseLong(getConfig(threadName + "_busysleep" , "1000")), + Long.parseLong(getConfig(threadName + "_memprereq" , "1000000"))); } - public void deployThread(String threadName, String threadShortDescription, String threadLongDescription, serverThread newThread, long startupDelay, long initialIdleSleep, long initialBusySleep) { + public void deployThread( + String threadName, + String threadShortDescription, + String threadLongDescription, + serverThread newThread, + long startupDelay, + long initialIdleSleep, + long initialBusySleep, + long initialMemoryPreRequisite) { if (newThread.isAlive()) throw new RuntimeException("undeployed threads must not live; they are started as part of the deployment"); newThread.setStartupSleep(startupDelay); - long sleep; + long x; try { - sleep = Long.parseLong(getConfig(threadName + "_idlesleep" , "novalue")); - newThread.setIdleSleep(sleep); + x = Long.parseLong(getConfig(threadName + "_idlesleep" , "novalue")); + newThread.setIdleSleep(x); } catch (NumberFormatException e) { newThread.setIdleSleep(initialIdleSleep); setConfig(threadName + "_idlesleep", initialIdleSleep); } try { - sleep = Long.parseLong(getConfig(threadName + "_busysleep" , "novalue")); - newThread.setBusySleep(sleep); + x = Long.parseLong(getConfig(threadName + "_busysleep" , "novalue")); + newThread.setBusySleep(x); } catch (NumberFormatException e) { newThread.setBusySleep(initialBusySleep); setConfig(threadName + "_busysleep", initialBusySleep); } + try { + x = Long.parseLong(getConfig(threadName + "_memprereq" , "novalue")); + newThread.setMemPreReqisite(x); + } catch (NumberFormatException e) { + newThread.setMemPreReqisite(initialMemoryPreRequisite); + setConfig(threadName + "_memprereq", initialMemoryPreRequisite); + } newThread.setLog(log); newThread.setDescription(threadShortDescription, threadLongDescription); workerThreads.put(threadName, newThread); @@ -290,11 +311,12 @@ public abstract class serverAbstractSwitch implements serverSwitch { return (serverThread) workerThreads.get(threadName); } - public void setThreadSleep(String threadName, long idleMillis, long busyMillis) { + public void setThreadPerformance(String threadName, long idleMillis, long busyMillis, long memprereqBytes) { serverThread thread = (serverThread) workerThreads.get(threadName); if (thread != null) { thread.setIdleSleep(idleMillis); thread.setBusySleep(busyMillis); + thread.setMemPreReqisite(memprereqBytes); } } diff --git a/source/de/anomic/server/serverAbstractThread.java b/source/de/anomic/server/serverAbstractThread.java index 7f9210443..abeb5847e 100644 --- a/source/de/anomic/server/serverAbstractThread.java +++ b/source/de/anomic/server/serverAbstractThread.java @@ -57,10 +57,10 @@ public abstract class serverAbstractThread extends Thread implements serverThrea private long startup = 0, idlePause = 0, busyPause = 0, blockPause = 0; private boolean running = true; private serverLog log = null; - private long idletime = 0, busytime = 0; + private long idletime = 0, busytime = 0, memprereq = 0; private String shortDescr = "", longDescr = ""; private long threadBlockTimestamp = System.currentTimeMillis(); - private long idleCycles = 0, busyCycles = 0; + private long idleCycles = 0, busyCycles = 0, outofmemoryCycles = 0; protected final void announceThreadBlockApply() { // shall only be used, if a thread blocks for an important reason @@ -107,6 +107,11 @@ public abstract class serverAbstractThread extends Thread implements serverThrea busyPause = milliseconds; } + public void setMemPreReqisite(long freeBytes) { + // sets minimum required amount of memory for the job execution + memprereq = freeBytes; + } + public final String getShortDescription() { return this.shortDescr; } @@ -125,6 +130,12 @@ public abstract class serverAbstractThread extends Thread implements serverThrea return this.busyCycles; } + public long getOutOfMemoryCycles() { + // returns the total number of cycles where + // a job execution was omitted because of memory shortage + return this.outofmemoryCycles; + } + public final long getBlockTime() { // returns the total time that this thread has been blocked so far return this.blockPause; @@ -206,8 +217,10 @@ public abstract class serverAbstractThread extends Thread implements serverThrea long innerpause; long timestamp; boolean isBusy; + Runtime rt = Runtime.getRuntime(); + while (running) { - try { + if (rt.freeMemory() > memprereq) try { // do job timestamp = System.currentTimeMillis(); isBusy = this.job(); @@ -224,6 +237,14 @@ public abstract class serverAbstractThread extends Thread implements serverThrea // if the exception is too bad it should call terminate() this.jobExceptionHandler(e); busyCycles++; + } else { + // omit job, not enough memory + // process scheduled pause + timestamp = System.currentTimeMillis(); + ratz(this.idlePause); + idletime += System.currentTimeMillis() - timestamp; + outofmemoryCycles++; + if (rt.freeMemory() <= memprereq) System.gc(); // give next loop a chance } } this.close(); diff --git a/source/de/anomic/server/serverInstantThread.java b/source/de/anomic/server/serverInstantThread.java index 57a6fd86f..3329063c6 100644 --- a/source/de/anomic/server/serverInstantThread.java +++ b/source/de/anomic/server/serverInstantThread.java @@ -117,6 +117,7 @@ public final class serverInstantThread extends serverAbstractThread implements s thread.setStartupSleep(startupDelay); thread.setIdleSleep(-1); thread.setBusySleep(-1); + thread.setMemPreReqisite(0); thread.setLog(log); thread.start(); return thread; diff --git a/source/de/anomic/server/serverSwitch.java b/source/de/anomic/server/serverSwitch.java index c695ae5be..24eabff19 100644 --- a/source/de/anomic/server/serverSwitch.java +++ b/source/de/anomic/server/serverSwitch.java @@ -73,9 +73,11 @@ public interface serverSwitch { String threadShortDescription, String threadLongDescription, serverThread newThread, - long startupDelay, long initialIdleSleep, long initialBusySleep); + long startupDelay, + long initialIdleSleep, long initialBusySleep, + long initialMemoryPreRequisite); public serverThread getThread(String threadName); - public void setThreadSleep(String threadName, long idleMillis, long busyMillis); + public void setThreadPerformance(String threadName, long idleMillis, long busyMillis, long memprereq); public void terminateThread(String threadName, boolean waitFor); public void terminateAllThreads(boolean waitFor); public Iterator /*of serverThread-Names (String)*/ threadNames(); diff --git a/source/de/anomic/server/serverThread.java b/source/de/anomic/server/serverThread.java index 6d2d9f8d6..91c4126c9 100644 --- a/source/de/anomic/server/serverThread.java +++ b/source/de/anomic/server/serverThread.java @@ -65,6 +65,9 @@ public interface serverThread { public void setBusySleep(long milliseconds); // sets a sleep time for pauses between two jobs if the job returns true (busy) + public void setMemPreReqisite(long freeBytes); + // sets minimum required amount of memory for the job execution + public String getShortDescription(); // returns short description string for online display @@ -77,6 +80,10 @@ public interface serverThread { public long getBusyCycles(); // returns the total number of cycles of job execution with busy-result + public long getOutOfMemoryCycles(); + // returns the total number of cycles where + // a job execution was omitted because of memory shortage + public long getBlockTime(); // returns the total time that this thread has been blocked so far diff --git a/source/yacy.java b/source/yacy.java index 6632e210d..ba5e2f289 100644 --- a/source/yacy.java +++ b/source/yacy.java @@ -291,7 +291,7 @@ public final class yacy { serverLog.logFailure("STARTUP", "Failed to start server. Probably port " + port + " already in use."); } else { // first start the server - sb.deployThread("10_httpd", "HTTPD Server/Proxy", "the HTTPD, used as web server and proxy", server, 0, 0, 0); + sb.deployThread("10_httpd", "HTTPD Server/Proxy", "the HTTPD, used as web server and proxy", server, 0, 0, 0, 0); //server.start(); // open the browser window diff --git a/yacy.init b/yacy.init index 1013bd542..7b4d2b46d 100644 --- a/yacy.init +++ b/yacy.init @@ -392,24 +392,36 @@ xpstopw=true # the idlesleep is the pause that an proces sleeps if the last call to the # process job was without execution of anything; # the busysleep is the pause after a full job execution +# the prereq-value is a memory pre-requisite: that much bytes must +# be available/free in the heap; othervise the loop is not executed +# and another idlesleep is performed 20_dhtdistribution_idlesleep=20000 20_dhtdistribution_busysleep=5000 +20_dhtdistribution_memprereq=5000000 30_peerping_idlesleep=120000 30_peerping_busysleep=120000 +30_peerping_memprereq=20000 40_peerseedcycle_idlesleep=1800000 40_peerseedcycle_busysleep=1200000 -50_localcrawl_idlesleep=10000 +40_peerseedcycle_memprereq=2000000 +50_localcrawl_idlesleep=1000 50_localcrawl_busysleep=200 -61_globalcrawltrigger_idlesleep=10000 +50_localcrawl_memprereq=4000000 +61_globalcrawltrigger_idlesleep=2000 61_globalcrawltrigger_busysleep=200 +61_globalcrawltrigger_memprereq=4000000 62_remotetriggeredcrawl_idlesleep=10000 62_remotetriggeredcrawl_busysleep=200 +62_remotetriggeredcrawl_memprereq=5000000 70_cachemanager_idlesleep=1000 70_cachemanager_busysleep=0 +70_cachemanager_memprereq=10000 80_indexing_idlesleep=1000 80_indexing_busysleep=0 +80_indexing_memprereq=2000000 90_cleanup_idlesleep=300000 90_cleanup_busysleep=300000 +90_cleanup_memprereq=10000 # multiprocessor-settings # you may want to run time-consuming processes on several processors @@ -422,17 +434,17 @@ xpstopw=true # ram cache for database files -# ram cache for indexCache.db -ramCacheRWI = 16777216 +# ram cache for assortment cache cluster (for all 50 files) +ramCacheRWI = 8388608 # ram cache for responseHeader.db ramCacheHTTP = 1048576 # ram cache for urlHash.db -ramCacheLURL = 8388608 +ramCacheLURL = 4194304 # ram cache for urlNotice.db -ramCacheNURL = 1048576 +ramCacheNURL = 524288 # ram cache for urlErr.db ramCacheEURL = 131072