3 import static org.testng.Assert.assertTrue;
5 import jalview.analysis.AlignmentGenerator;
6 import jalview.bin.Cache;
7 import jalview.bin.Jalview;
8 import jalview.io.DataSourceType;
9 import jalview.io.FileLoader;
12 import java.io.IOException;
13 import java.io.PrintStream;
15 import org.testng.annotations.BeforeClass;
16 import org.testng.annotations.Test;
18 public class FreeUpMemoryTest
20 private static final int ONE_MB = 1000 * 1000;
23 * Configure (read-only) Jalview property settings for test
25 @BeforeClass(alwaysRun = true)
28 Jalview.main(new String[] { "-nonews", "-props",
29 "test/jalview/testProps.jvprops" });
30 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
31 Boolean.TRUE.toString());
32 Cache.applicationProperties.setProperty("SHOW_QUALITY",
33 Boolean.TRUE.toString());
34 Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
35 Boolean.TRUE.toString());
36 Cache.applicationProperties.setProperty("SHOW_OCCUPANCY",
37 Boolean.TRUE.toString());
38 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
39 Boolean.TRUE.toString());
43 * A simple test that memory is released when all windows are closed.
45 * <li>generates a reasonably large alignment and loads it</li>
46 * <li>performs various operations on the alignment</li>
47 * <li>closes all windows</li>
48 * <li>requests garbage collection</li>
49 * <li>asserts that the remaining memory footprint (heap usage) is 'not large'
52 * If the test fails, this suggests that a reference to some large object
53 * (perhaps the alignment data, or consensus profile) has failed to be garbage
54 * collected. If this is the case, the heap will need to be inspected manually
55 * (suggest using jvisualvm) in order to track down where large objects are
56 * still referenced. The code (for example AlignmentViewport.dispose()) should
57 * then be updated to ensure references to large objects are set to null when
58 * they are no longer required.
62 @Test(groups = "Memory")
63 public void testFreeMemoryOnClose() throws IOException
65 File f = generateAlignment();
69 * load alignment, wait for consensus and other threads to complete
71 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(f.getPath(),
73 waitForThreads(af.getViewport());
75 af.closeMenuItem_actionPerformed(true);
78 * request garbage collection and wait briefly for it to run;
79 * NB there is no guarantee when, or whether, it will do so
87 } catch (InterruptedException e)
93 * a second gc() call should not be necessary - but it is!
94 * the test passes with it, and fails without it
99 * check used memory is 'reasonably low'
101 long availableMemory = Runtime.getRuntime().totalMemory() / ONE_MB;
102 long freeMemory = Runtime.getRuntime().freeMemory() / ONE_MB;
103 long usedMemory = availableMemory - freeMemory;
104 System.out.println("Memory in use after close all windows: "
105 + usedMemory + "MB");
108 * if this assertion fails
109 * - set a breakpoint here
110 * - run jvisualvm to inspect a heap dump of Jalview
111 * - identify large objects in the heap and their referers
112 * - fix code as necessary to null the references on close
114 long expectedMax = 30L; // typically reports around 25
115 assertTrue(usedMemory < expectedMax, String.format(
116 "Used memory %d should be less than %d", usedMemory,
121 * wait for consensus etc thread to complete
125 protected void waitForThreads(AlignViewport av)
127 while (av.isCalcInProgress())
132 } catch (Exception x)
139 * Generates an alignment and saves it in a temporary file, to be loaded by
140 * Jalview. We use a peptide alignment (so Conservation and Quality are
141 * calculated), which is wide enough to ensure Consensus, Conservation and
142 * Occupancy have a significant memory footprint (if not removed from the
146 * @throws IOException
148 private File generateAlignment() throws IOException
150 File f = File.createTempFile("MemoryTest", "fa");
151 PrintStream ps = new PrintStream(f);
152 AlignmentGenerator ag = new AlignmentGenerator(false, ps);
155 ag.generate(width, height, 0, 10, 15);