summaryrefslogtreecommitdiffstats
path: root/logo/src/xlogo/MemoryChecker.java
diff options
context:
space:
mode:
authorMarko Živković <[email protected]>2014-06-11 10:10:33 +0000
committerMarko Živković <[email protected]>2014-06-11 10:10:33 +0000
commit1107aa0763e3d7554408c401d2a1dbed11a94c51 (patch)
tree7074264bc7b63f2ee5ee14a39458380fcce1904b /logo/src/xlogo/MemoryChecker.java
Add initial directories and files
git-svn-id: https://svn.code.sf.net/p/xlogo4schools/svn/trunk@1 3b0d7934-f7ef-4143-9606-b51f2e2281fd
Diffstat (limited to 'logo/src/xlogo/MemoryChecker.java')
-rw-r--r--logo/src/xlogo/MemoryChecker.java163
1 files changed, 163 insertions, 0 deletions
diff --git a/logo/src/xlogo/MemoryChecker.java b/logo/src/xlogo/MemoryChecker.java
new file mode 100644
index 0000000..f35f73a
--- /dev/null
+++ b/logo/src/xlogo/MemoryChecker.java
@@ -0,0 +1,163 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * a lot of modifications, extensions, refactorings have been applied by Marko Zivkovic
+ */
+
+/**
+ * Title : XLogo
+ * Description : XLogo is an interpreter for the Logo
+ * programming language
+ *
+ * @author Loïc Le Coq
+ **/
+package xlogo;
+
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.storage.global.GlobalConfig;
+
+/**
+ * This class is a thread that prevents from memory Overflow <br>
+ * Those problems could happen when a program loops indefinitely<br>
+ * Eg:<br>
+ * <br>
+ * <tt>
+ * To bad<br>
+ * fd 1 rt 1 <br>
+ * bad<br>
+ * this lines will explode memory<br>
+ * end <br>
+ * </tt>
+ *
+ * @author loic
+ *
+ * @author Marko Zivkovic - Extensive tests and provocation of the memory usage error message have shown
+ * that in XLogo4Schools, using a maximum 128MB heap, the memory threshold is never reached
+ * (Or very, very late in a gigantic recursion).
+ *
+ */
+public class MemoryChecker extends Thread
+{
+ /**
+ * The main frame
+ */
+ private Application cadre;
+ /**
+ * This boolean indicates if the thread has to continue.<br>
+ * If false, the thread will stop.
+ */
+ private boolean alive;
+
+ /**
+ * Constructs the Memory Checker for the main Frame
+ *
+ * @param cadre
+ * the main Frame
+ */
+ public MemoryChecker(Application cadre)
+ {
+ this.cadre = cadre;
+ }
+
+ private static int maxSleepTime = 10000;
+ private static int minSleepTime = 500;
+ private static int sleepRange = maxSleepTime - minSleepTime;
+
+ /**
+ * The Run Method for the Thread
+ */
+ public void run()
+ {
+ /*
+ * Marko : I reduced the amount of calculations done in every iteration.
+ * Before it included 1 subtraction and 2 divisions and a fetch from GlobalConfig,
+ * now only 1 subtraction is used to determine consumed > consumptionThreshold
+ * and another long comparison was added to regulate frequency of memory checks.
+ */
+ long consumptionThreshold = GlobalConfig.getMemoryThreshold();
+ long listenThreshold = (long) (0.8 * consumptionThreshold);
+
+
+ /*
+ * I increased default sleeping time to about 10 seconds, because a check every 1 second is too much overhead for doing nothing useful.
+ * However, as soon as the listenThreshold is reached, the sleepTime will start to decrease.
+ * Only once the listenThreshold is reached,
+ * the MemoryChecker becomes important to prevent an OutOfMemoryError and start suggesting the garbage collector to work.)
+ */
+ int sleepTime = maxSleepTime;
+
+ alive = true;
+
+ while (alive)
+ {
+ try
+ {
+ Thread.sleep(sleepTime);
+ }
+ catch (InterruptedException ignore)
+ {}
+ long free = Runtime.getRuntime().freeMemory();
+ long total = Runtime.getRuntime().totalMemory();
+ long consumed = (total - free);
+
+ if (consumed >= listenThreshold)
+ {
+ sleepTime = (int) (maxSleepTime - consumed / total * sleepRange);
+
+ /*
+ * Marko :
+ * In XLogo, when the error dialog was displayed, it usually kept displaying several times, disrupting any further use of the interpreter.
+ * The only out was to restart the application. This indicates that, although heavy memory usage was detected by this thread,
+ * the garbage collector did not yet start to free memory from dead objects.
+ * (Discussions about GC in the Internet indicate that the Java GC starts working as soon as a heap generation gets full.
+ * It is possible that the young generation is not full enough when 0.9*MaxMemory is reached, thus the message keeps appearing all the time,
+ * because memory is not sufficiently cleaned up.)
+ * Therefore, at least suggest the GC that it would be a good moment for garbage collection, and help recover. That's the best we can do.
+ */
+ System.gc();
+ }
+ else
+ sleepTime = maxSleepTime;
+
+ if (consumed > consumptionThreshold)
+ {
+ cadre.error = true;
+ alive = false;
+ DialogMessenger.getInstance().dispatchError(Logo.messages.getString("erreur"),
+ Logo.messages.getString("depassement_memoire"));
+ }
+ }
+ }
+
+ /**
+ * Causes the memory checker loop to break.
+ * @author Marko
+ */
+ public void kill()
+ {
+ alive = false;
+ }
+
+}