X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=test%2Fjalview%2Fgui%2FFreeUpMemoryTest.java;h=a9eca49e235fb9e36868f21cdc0062859542624e;hb=279c6495df1a0de231600a2d283098c7411c4730;hp=277c27e30f7cd5dcb1c72b35e774c99e177989e2;hpb=f6d3b491c392914981b65fee21df51b530ee80f7;p=jalview.git
diff --git a/test/jalview/gui/FreeUpMemoryTest.java b/test/jalview/gui/FreeUpMemoryTest.java
index 277c27e..a9eca49 100644
--- a/test/jalview/gui/FreeUpMemoryTest.java
+++ b/test/jalview/gui/FreeUpMemoryTest.java
@@ -1,17 +1,28 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview 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 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview 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 Jalview. If not, see .
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
package jalview.gui;
-import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
-import jalview.analysis.AlignmentGenerator;
-import jalview.bin.Cache;
-import jalview.bin.Jalview;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SequenceGroup;
-import jalview.io.DataSourceType;
-import jalview.io.FileLoader;
-
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
@@ -20,6 +31,13 @@ import java.io.PrintStream;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import jalview.analysis.AlignmentGenerator;
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceGroup;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
import junit.extensions.PA;
/**
@@ -48,7 +66,7 @@ import junit.extensions.PA;
*
Tips:
*
* - Perform GC from the Monitor view in visualvm before requesting the heap
- * dump
+ * dump - test failure might be simply a delay to GC
* - View 'Objects' and filter classes to {@code jalview}. Sort columns by
* Count, or Size, and look for anything suspicious. For example, if the object
* count for {@code Sequence} is non-zero (it shouldn't be), pick any instance,
@@ -89,6 +107,11 @@ public class FreeUpMemoryTest
{
private static final int ONE_MB = 1000 * 1000;
+ /*
+ * maximum retained heap usage (in MB) for a passing test
+ */
+ private static int MAX_RESIDUAL_HEAP = 45;
+
/**
* Configure (read-only) Jalview property settings for test
*/
@@ -109,24 +132,30 @@ public class FreeUpMemoryTest
@Test(groups = "Memory")
public void testFreeMemoryOnClose() throws IOException
{
- long expectedMin = 37L;
-
File f = generateAlignment();
f.deleteOnExit();
doStuffInJalview(f);
- Desktop.instance.closeAll_actionPerformed(null);
+ if (Desktop.instance != null)
+ Desktop.instance.closeAll_actionPerformed(null);
- checkUsedMemory(expectedMin);
+ checkUsedMemory(MAX_RESIDUAL_HEAP);
}
- private static long getUsedMemory()
+ /**
+ * Returns the current total used memory (available memory - free memory),
+ * rounded down to the nearest MB
+ *
+ * @return
+ */
+ private static int getUsedMemory()
{
- long availableMemory = Runtime.getRuntime().totalMemory() / ONE_MB;
- long freeMemory = Runtime.getRuntime().freeMemory() / ONE_MB;
+ long availableMemory = Runtime.getRuntime().totalMemory();
+ long freeMemory = Runtime.getRuntime().freeMemory();
long usedMemory = availableMemory - freeMemory;
- return usedMemory;
+
+ return (int) (usedMemory / ONE_MB);
}
/**
@@ -135,43 +164,43 @@ public class FreeUpMemoryTest
*
* @param expectedMax
*/
- protected void checkUsedMemory(long expectedMax)
+ protected void checkUsedMemory(int expectedMax)
{
/*
- * request garbage collection and wait for it to run;
+ * request garbage collection and wait for it to run (up to 3 times);
* NB there is no guarantee when, or whether, it will do so
- * wait time depends on JRE/processor, generous allowance here
*/
- System.gc();
- waitFor(1500);
-
- /*
- * a second gc() call should not be necessary - but it is!
- * the test passes with it, and fails without it
- */
- System.gc();
- waitFor(1500);
-
- /*
- * check used memory is 'reasonably low'
- */
- long usedMemory = getUsedMemory();
- /*
- * sanity check - fails if any frame was added after
- * closeAll_actionPerformed
- */
- assertEquals(Desktop.instance.getAllFrames().length, 0);
+ long usedMemory = 0L;
+ Long minUsedMemory = null;
+ int gcCount = 0;
+ while (gcCount < 3)
+ {
+ gcCount++;
+ System.gc();
+ waitFor(1500);
+ usedMemory = getUsedMemory();
+ if (minUsedMemory == null || usedMemory < minUsedMemory)
+ {
+ minUsedMemory = usedMemory;
+ }
+ if (usedMemory < expectedMax)
+ {
+ break;
+ }
+ }
/*
- * if this assertion fails
- * - set a breakpoint here
- * - run jvisualvm to inspect a heap dump of Jalview
- * - identify large objects in the heap and their referers
+ * if this assertion fails (reproducibly!)
+ * - set a breakpoint here, conditional on (usedMemory > expectedMax)
+ * - run VisualVM to inspect the heap usage, and run GC from VisualVM to check
+ * it is not simply delayed garbage collection causing the test failure
+ * - take a heap dump and identify large objects in the heap and their referers
* - fix code as necessary to null the references on close
*/
- System.out.println("Used memory after gc = " + usedMemory
- + "MB (should be <" + expectedMax + ")");
- assertTrue(usedMemory < expectedMax, String.format(
+ System.out.println("(Minimum) Used memory after " + gcCount
+ + " call(s) to gc() = " + minUsedMemory + "MB (should be <="
+ + expectedMax + ")");
+ assertTrue(usedMemory <= expectedMax, String.format(
"Used memory %d should be less than %d (Recommend running test manually to verify)",
usedMemory, expectedMax));
}