Hi Doug-
Whoa! That's some leak.
Doug Lindholm wrote:
A few months back I reported a problem I was seeing with running out of
memory. It has now escalated to become a show-stopping problem. I've
been doing some profiling to see where the resources are going.
I've attached a simple sample program that demonstrates one such case. I
make a Display, add a ScalarMap to it, then repeatedly setRange. When
using a DisplayImplJ3D the instance count of Object[] and many java3d
classes continues to grow. There is no such problem with the
DisplayImplJ2D. I know very little about java3d. I'm hoping there is
something VisAD can do to free up java3d resources and that this is not
a java3d bug that we have no control over.
Any ideas?
I modified your test slightly to add the display to a frame.
When I did this, my total memory useage stayed around 7 Mb
and I could see garbage collection running.
If I don't add the display to a frame, memory use shoots
through the roof. I've attached the revised program and
a small memory monitor program. If you pass in a parameter
to the MemoryTest, it will show the display, otherwise,
just the monitor.
I don't have time to track down the cause, but maybe this
will help Tom Rink or one of the other developers. Thanks
for the test program.
Don
*************************************************************
Don Murray UCAR Unidata Program
dmurray@xxxxxxxxxxxxxxxx P.O. Box 3000
(303) 497-8628 Boulder, CO 80307
http://www.unidata.ucar.edu/staff/donm
*************************************************************
import visad.*;
import visad.java2d.*;
import visad.java3d.*;
import javax.swing.*;
import java.awt.event.*;
public class MemoryTest {
public void init(boolean showDisplay) {
try {
//System.out.println("make display");
//DisplayImplJ2D display = new DisplayImplJ2D( "test" );
DisplayImplJ3D display = new DisplayImplJ3D( "test" );
//DisplayImplJ3D display = new DisplayImplJ3D( "test", new
TwoDDisplayRendererJ3D() );
//System.out.println("make map");
ScalarMap xmap = new ScalarMap( RealType.Time, Display.XAxis );
//System.out.println("add map");
display.addMap(xmap);
JFrame frame = new JFrame("Memory Test");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
if (showDisplay) frame.getContentPane().add(display.getComponent());
frame.getContentPane().add("South", new MemoryMonitor());
frame.pack();
frame.show();
int count = 0;
while ( true ) {
double now = (double) (System.currentTimeMillis() / 1000.0);
// System.out.println("step " + count++ + " now = " + now );
double then = now - 3600.0;
xmap.setRange(then, now);
//Thread.sleep(10);
}
}
catch (Throwable t) {
t.printStackTrace();
}
}
public static void main(String[] args) {
MemoryTest test = new MemoryTest();
test.init(args.length > 0);
}
}
// $Id: MemoryMonitor.java,v 1.4 2002/05/03 13:54:42 dmurray Exp $
/*
* Copyright 1997-2000 Unidata Program Center/University Corporation for
* Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
* support@xxxxxxxxxxxxxxxx.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library 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 Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
import java.text.DecimalFormat;
public class MemoryMonitor extends JPanel implements Runnable
{
boolean running = false;
long sleepInterval = 2000;
Thread thread;
int percentThreshold = 80;
int timesAboveThreshold = 0;
static DecimalFormat fmt = new DecimalFormat("#0.00 MB");
JLabel label1 = new JLabel ("");
JLabel label2 = new JLabel ("");
Color labelForeground;
public MemoryMonitor () {
setLayout (new FlowLayout (FlowLayout.LEFT));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(label1);
add(label2);
//GuiUtils.hbox (this, Misc.newList (label1, label2));
MouseListener ml = new MouseAdapter () {
public void mouseClicked (MouseEvent e) {
if (running) stop ();
else start ();
}
};
labelForeground = label2.getForeground ();
label1.addMouseListener (ml);
label2.addMouseListener (ml);
start ();
}
private synchronized void stop () {
running = false;
label1.setEnabled (false);
label2.setEnabled (false);
}
private synchronized void start () {
if (running) return;
label1.setEnabled (true);
label2.setEnabled (true);
running = true;
thread = new Thread ( this, "Memory monitor");
thread.start ();
}
private void showStats () {
double totalMemory = (double) Runtime.getRuntime ().totalMemory ();
double freeMemory = (double) Runtime.getRuntime ().freeMemory ();
double usedMemory = (totalMemory-freeMemory);
int percent = (int)(100.0*(usedMemory/totalMemory));
totalMemory = totalMemory/1000000.0;
usedMemory = usedMemory/1000000.0;
label1.setText ("Memory usage: total: " + fmt.format (totalMemory) +
" used: " + fmt.format (usedMemory));
label2.setText (" (" + percent +"%)");
// doing this continually slows things down
//Runtime.getRuntime ().gc ();
if (percent > percentThreshold) {
timesAboveThreshold ++;
if (timesAboveThreshold > 5)
label2.setForeground (Color.red);
Runtime.getRuntime ().gc ();
} else {
label2.setForeground (labelForeground);
timesAboveThreshold = 0;
}
}
public void run () {
while (running) {
showStats ();
try {thread.sleep (sleepInterval);} catch (Exception exc) {}
}
}
public void setRunning (boolean r) {
running = r;
}
public boolean getRunning () {
return running;
}
public static void main (String[]args) {
JFrame f = new JFrame ();
MemoryMonitor mm = new MemoryMonitor ();
f.getContentPane ().add (mm);
f.pack ();
f.show ();
}
}